[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>(
|
internal class JavaElementDelegatingTypeParameterBoundTypeSourceWithSmartPointer<TYPE : PsiType>(
|
||||||
override val psiPointer: SmartPsiElementPointer<out PsiTypeParameter>,
|
override val psiPointer: SmartPsiElementPointer<out PsiTypeParameter>,
|
||||||
private val boundIndex: Int,
|
private val boundIndex: Int,
|
||||||
@@ -68,3 +67,11 @@ internal class JavaElementDelegatingSuperTypeSourceWithSmartPointer(
|
|||||||
) : JavaElementDelegatingTypeSourceWithSmartPointer<PsiClass, PsiClassType>() {
|
) : JavaElementDelegatingTypeSourceWithSmartPointer<PsiClass, PsiClassType>() {
|
||||||
override fun getType(psi: PsiClass): PsiClassType = psi.superTypes[superTypeIndex]
|
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)
|
require(psiExpressionSource is JavaElementPsiSourceWithSmartPointer)
|
||||||
return JavaElementDelegatingExpressionTypeSourceWithSmartPointer(psiExpressionSource.pointer, psiExpressionSource.factory)
|
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");
|
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
|
@Test
|
||||||
public void testAllFilesPresentInResolve() throws Exception {
|
public void testAllFilesPresentInResolve() throws Exception {
|
||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
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");
|
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
|
@Test
|
||||||
public void testAllFilesPresentInResolve() throws Exception {
|
public void testAllFilesPresentInResolve() throws Exception {
|
||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
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");
|
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 {
|
public void testAllFilesPresentInResolve() throws Exception {
|
||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
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");
|
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
|
@Test
|
||||||
public void testAllFilesPresentInResolve() throws Exception {
|
public void testAllFilesPresentInResolve() throws Exception {
|
||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
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");
|
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
|
@Test
|
||||||
public void testAllFilesPresentInResolve() throws Exception {
|
public void testAllFilesPresentInResolve() throws Exception {
|
||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
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 {
|
}.apply {
|
||||||
if (modality == Modality.SEALED) {
|
if (modality == Modality.SEALED) {
|
||||||
val inheritors = javaClass.permittedTypes.mapNotNull { classifierType ->
|
val permittedTypes = javaClass.permittedTypes
|
||||||
val classifier = classifierType.classifier as? JavaClass
|
setSealedClassInheritors {
|
||||||
classifier?.let { JavaToKotlinClassMap.mapJavaToKotlin(it.fqName!!) }
|
permittedTypes.mapNotNull { classifierType ->
|
||||||
|
val classifier = classifierType.classifier as? JavaClass
|
||||||
|
classifier?.let { JavaToKotlinClassMap.mapJavaToKotlin(it.fqName!!) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setSealedClassInheritors(inheritors)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (classIsAnnotation) {
|
if (classIsAnnotation) {
|
||||||
|
|||||||
+9
-3
@@ -23,7 +23,7 @@ private val FirSession.sealedClassInheritorsProvider: SealedClassInheritorsProvi
|
|||||||
object SealedClassInheritorsProviderImpl : SealedClassInheritorsProvider() {
|
object SealedClassInheritorsProviderImpl : SealedClassInheritorsProvider() {
|
||||||
@OptIn(SealedClassInheritorsProviderInternals::class)
|
@OptIn(SealedClassInheritorsProviderInternals::class)
|
||||||
override fun getSealedClassInheritors(firClass: FirRegularClass): List<ClassId> {
|
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)
|
@OptIn(SealedClassInheritorsProviderInternals::class)
|
||||||
fun FirRegularClass.setSealedClassInheritors(inheritors: List<ClassId>) {
|
fun FirRegularClass.setSealedClassInheritors(inheritors: List<ClassId>) {
|
||||||
require(this.isSealed)
|
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()
|
private object SealedClassInheritorsKey : FirDeclarationDataKey()
|
||||||
|
|
||||||
@SealedClassInheritorsProviderInternals
|
@SealedClassInheritorsProviderInternals
|
||||||
var FirRegularClass.sealedInheritorsAttr: List<ClassId>? by FirDeclarationDataRegistry.data(SealedClassInheritorsKey)
|
var FirRegularClass.sealedInheritorsAttr: Lazy<List<ClassId>>? by FirDeclarationDataRegistry.data(SealedClassInheritorsKey)
|
||||||
private set
|
private set
|
||||||
|
|||||||
+3
-1
@@ -69,7 +69,9 @@ class JavaClassImpl(psiClassSource: JavaElementPsiSource<PsiClass>) : JavaClassi
|
|||||||
get() = JavaElementUtil.isSealed(this)
|
get() = JavaElementUtil.isSealed(this)
|
||||||
|
|
||||||
override val permittedTypes: Collection<JavaClassifierType>
|
override val permittedTypes: Collection<JavaClassifierType>
|
||||||
get() = classifierTypes(psi.permitsListTypes, sourceFactory)
|
get() = psi.permitsListTypes.convertIndexed { index, _ ->
|
||||||
|
JavaClassifierTypeImpl(sourceFactory.createPermittedTypeSource(psiElementSource, index))
|
||||||
|
}
|
||||||
|
|
||||||
override val isRecord: Boolean
|
override val isRecord: Boolean
|
||||||
get() = psi.isRecord
|
get() = psi.isRecord
|
||||||
|
|||||||
+15
@@ -26,6 +26,14 @@ abstract class JavaElementSourceFactory {
|
|||||||
|
|
||||||
abstract fun <TYPE : PsiType> createExpressionTypeSource(psiExpressionSource: JavaElementPsiSource<out PsiExpression>): JavaElementTypeSource<TYPE>
|
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 {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getInstance(project: Project): JavaElementSourceFactory {
|
fun getInstance(project: Project): JavaElementSourceFactory {
|
||||||
@@ -63,6 +71,13 @@ class JavaFixedElementSourceFactory : JavaElementSourceFactory() {
|
|||||||
return createTypeSource(psiTypeParameterSource.psi.superTypes[superTypeIndex])
|
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> {
|
override fun <TYPE : PsiType> createExpressionTypeSource(psiExpressionSource: JavaElementPsiSource<out PsiExpression>): JavaElementTypeSource<TYPE> {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
return createTypeSource(psiExpressionSource.psi.type as TYPE)
|
return createTypeSource(psiExpressionSource.psi.type as TYPE)
|
||||||
|
|||||||
Reference in New Issue
Block a user