[LL FIR, Java] fix resolve contract violation from java symbol provider from permits
To create a smart psi type pointer, IJ Platform uses resolve We cannot use resolve from JavaSymbolProvider, as it may lead to resolve contract violation ^KT-59243 Fixed
This commit is contained in:
committed by
Space Team
parent
5af8b9e819
commit
7631e90f12
+8
-1
@@ -48,7 +48,6 @@ internal class JavaElementDelegatingExpressionTypeSourceWithSmartPointer<TYPE :
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal class JavaElementDelegatingTypeParameterBoundTypeSourceWithSmartPointer<TYPE : PsiType>(
|
||||
override val psiPointer: SmartPsiElementPointer<out PsiTypeParameter>,
|
||||
private val boundIndex: Int,
|
||||
@@ -68,3 +67,11 @@ internal class JavaElementDelegatingSuperTypeSourceWithSmartPointer(
|
||||
) : JavaElementDelegatingTypeSourceWithSmartPointer<PsiClass, PsiClassType>() {
|
||||
override fun getType(psi: PsiClass): PsiClassType = psi.superTypes[superTypeIndex]
|
||||
}
|
||||
|
||||
internal class JavaElementDelegatingPermittedTypeSourceWithSmartPointer(
|
||||
override val psiPointer: SmartPsiElementPointer<out PsiClass>,
|
||||
private val permittedTypeIndex: Int,
|
||||
override val factory: JavaElementSourceFactory,
|
||||
) : JavaElementDelegatingTypeSourceWithSmartPointer<PsiClass, PsiClassType>() {
|
||||
override fun getType(psi: PsiClass): PsiClassType = psi.permitsListTypes[permittedTypeIndex]
|
||||
}
|
||||
|
||||
+12
@@ -61,4 +61,16 @@ class JavaElementSourceWithSmartPointerFactory(project: Project) : JavaElementSo
|
||||
require(psiExpressionSource is JavaElementPsiSourceWithSmartPointer)
|
||||
return JavaElementDelegatingExpressionTypeSourceWithSmartPointer(psiExpressionSource.pointer, psiExpressionSource.factory)
|
||||
}
|
||||
|
||||
override fun createPermittedTypeSource(
|
||||
psiTypeParameterSource: JavaElementPsiSource<out PsiClass>,
|
||||
permittedTypeIndex: Int
|
||||
): JavaElementTypeSource<PsiClassType> {
|
||||
require(psiTypeParameterSource is JavaElementPsiSourceWithSmartPointer)
|
||||
return JavaElementDelegatingPermittedTypeSourceWithSmartPointer(
|
||||
psiTypeParameterSource.pointer,
|
||||
permittedTypeIndex,
|
||||
psiTypeParameterSource.factory,
|
||||
)
|
||||
}
|
||||
}
|
||||
+6
@@ -39,6 +39,12 @@ public class DiagnosticCompilerTestFirTestdataTestGenerated extends AbstractDiag
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("accessJavaFromKotlinViaStaticImportAndPermits.kt")
|
||||
public void testAccessJavaFromKotlinViaStaticImportAndPermits() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImportAndPermits.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllFilesPresentInResolve() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
|
||||
+6
@@ -39,6 +39,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFirTestDataTestGenerated
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("accessJavaFromKotlinViaStaticImportAndPermits.kt")
|
||||
public void testAccessJavaFromKotlinViaStaticImportAndPermits() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImportAndPermits.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllFilesPresentInResolve() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
|
||||
+5
@@ -40,6 +40,11 @@ public class LazyBodyIsNotTouchedTestGenerated extends AbstractLazyBodyIsNotTouc
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("accessJavaFromKotlinViaStaticImportAndPermits.kt")
|
||||
public void testAccessJavaFromKotlinViaStaticImportAndPermits() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImportAndPermits.kt");
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInResolve() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
FILE: useSite.kt
|
||||
public final fun foo(): R|kotlin/Int| {
|
||||
^foo Int(4)
|
||||
}
|
||||
FILE: KotlinInterface.kt
|
||||
public abstract interface KotlinInterface : R|kotlin/Any| {
|
||||
public abstract var selectedOptions: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
public set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
Vendored
+24
@@ -0,0 +1,24 @@
|
||||
// FILE: useSite.kt
|
||||
|
||||
import InspectionProfileImpl.INIT_INSPECTIONS
|
||||
|
||||
fun foo(): Int = 4
|
||||
|
||||
// FILE: InspectionProfileImpl.java
|
||||
import static Configuration.StaticConfigurationClass
|
||||
|
||||
public abstract sealed class InspectionProfileImpl permits StaticConfigurationClass {
|
||||
public static boolean INIT_INSPECTIONS;
|
||||
}
|
||||
|
||||
// FILE: Configuration.java
|
||||
public class Configuration implements KotlinInterface {
|
||||
public static class StaticConfigurationClass {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: KotlinInterface.kt
|
||||
interface KotlinInterface {
|
||||
var selectedOptions: Int
|
||||
}
|
||||
+6
@@ -39,6 +39,12 @@ public class FirLightTreeDiagnosticsTestGenerated extends AbstractFirLightTreeDi
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("accessJavaFromKotlinViaStaticImportAndPermits.kt")
|
||||
public void testAccessJavaFromKotlinViaStaticImportAndPermits() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImportAndPermits.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllFilesPresentInResolve() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
|
||||
+6
@@ -39,6 +39,12 @@ public class FirPsiDiagnosticTestGenerated extends AbstractFirPsiDiagnosticTest
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("accessJavaFromKotlinViaStaticImportAndPermits.kt")
|
||||
public void testAccessJavaFromKotlinViaStaticImportAndPermits() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImportAndPermits.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllFilesPresentInResolve() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
|
||||
@@ -381,11 +381,13 @@ abstract class FirJavaFacade(
|
||||
}
|
||||
}.apply {
|
||||
if (modality == Modality.SEALED) {
|
||||
val inheritors = javaClass.permittedTypes.mapNotNull { classifierType ->
|
||||
val classifier = classifierType.classifier as? JavaClass
|
||||
classifier?.let { JavaToKotlinClassMap.mapJavaToKotlin(it.fqName!!) }
|
||||
val permittedTypes = javaClass.permittedTypes
|
||||
setSealedClassInheritors {
|
||||
permittedTypes.mapNotNull { classifierType ->
|
||||
val classifier = classifierType.classifier as? JavaClass
|
||||
classifier?.let { JavaToKotlinClassMap.mapJavaToKotlin(it.fqName!!) }
|
||||
}
|
||||
}
|
||||
setSealedClassInheritors(inheritors)
|
||||
}
|
||||
|
||||
if (classIsAnnotation) {
|
||||
|
||||
+9
-3
@@ -23,7 +23,7 @@ private val FirSession.sealedClassInheritorsProvider: SealedClassInheritorsProvi
|
||||
object SealedClassInheritorsProviderImpl : SealedClassInheritorsProvider() {
|
||||
@OptIn(SealedClassInheritorsProviderInternals::class)
|
||||
override fun getSealedClassInheritors(firClass: FirRegularClass): List<ClassId> {
|
||||
return firClass.sealedInheritorsAttr ?: emptyList()
|
||||
return firClass.sealedInheritorsAttr?.value ?: emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,11 +36,17 @@ fun FirRegularClass.getSealedClassInheritors(session: FirSession): List<ClassId>
|
||||
@OptIn(SealedClassInheritorsProviderInternals::class)
|
||||
fun FirRegularClass.setSealedClassInheritors(inheritors: List<ClassId>) {
|
||||
require(this.isSealed)
|
||||
sealedInheritorsAttr = inheritors.sortedBy { it.asFqNameString() }
|
||||
sealedInheritorsAttr = lazyOf(inheritors.sortedBy { it.asFqNameString() })
|
||||
}
|
||||
|
||||
@OptIn(SealedClassInheritorsProviderInternals::class)
|
||||
fun FirRegularClass.setSealedClassInheritors(inheritorComputer: () -> List<ClassId>) {
|
||||
require(this.isSealed)
|
||||
sealedInheritorsAttr = lazy { inheritorComputer().sortedBy { it.asFqNameString() } }
|
||||
}
|
||||
|
||||
private object SealedClassInheritorsKey : FirDeclarationDataKey()
|
||||
|
||||
@SealedClassInheritorsProviderInternals
|
||||
var FirRegularClass.sealedInheritorsAttr: List<ClassId>? by FirDeclarationDataRegistry.data(SealedClassInheritorsKey)
|
||||
var FirRegularClass.sealedInheritorsAttr: Lazy<List<ClassId>>? by FirDeclarationDataRegistry.data(SealedClassInheritorsKey)
|
||||
private set
|
||||
|
||||
+3
-1
@@ -69,7 +69,9 @@ class JavaClassImpl(psiClassSource: JavaElementPsiSource<PsiClass>) : JavaClassi
|
||||
get() = JavaElementUtil.isSealed(this)
|
||||
|
||||
override val permittedTypes: Collection<JavaClassifierType>
|
||||
get() = classifierTypes(psi.permitsListTypes, sourceFactory)
|
||||
get() = psi.permitsListTypes.convertIndexed { index, _ ->
|
||||
JavaClassifierTypeImpl(sourceFactory.createPermittedTypeSource(psiElementSource, index))
|
||||
}
|
||||
|
||||
override val isRecord: Boolean
|
||||
get() = psi.isRecord
|
||||
|
||||
+15
@@ -26,6 +26,14 @@ abstract class JavaElementSourceFactory {
|
||||
|
||||
abstract fun <TYPE : PsiType> createExpressionTypeSource(psiExpressionSource: JavaElementPsiSource<out PsiExpression>): JavaElementTypeSource<TYPE>
|
||||
|
||||
/**
|
||||
* @see com.intellij.psi.PsiClass.getPermitsListTypes
|
||||
*/
|
||||
abstract fun createPermittedTypeSource(
|
||||
psiTypeParameterSource: JavaElementPsiSource<out PsiClass>,
|
||||
permittedTypeIndex: Int,
|
||||
): JavaElementTypeSource<PsiClassType>
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun getInstance(project: Project): JavaElementSourceFactory {
|
||||
@@ -63,6 +71,13 @@ class JavaFixedElementSourceFactory : JavaElementSourceFactory() {
|
||||
return createTypeSource(psiTypeParameterSource.psi.superTypes[superTypeIndex])
|
||||
}
|
||||
|
||||
override fun createPermittedTypeSource(
|
||||
psiTypeParameterSource: JavaElementPsiSource<out PsiClass>,
|
||||
permittedTypeIndex: Int
|
||||
): JavaElementTypeSource<PsiClassType> {
|
||||
return createTypeSource(psiTypeParameterSource.psi.permitsListTypes[permittedTypeIndex])
|
||||
}
|
||||
|
||||
override fun <TYPE : PsiType> createExpressionTypeSource(psiExpressionSource: JavaElementPsiSource<out PsiExpression>): JavaElementTypeSource<TYPE> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return createTypeSource(psiExpressionSource.psi.type as TYPE)
|
||||
|
||||
Reference in New Issue
Block a user