[FE, Java resolve] Support inheritors of sealed Java type without permits clause
This fixes a false negative NO_ELSE_IN_WHEN in K2 and incidentally also fixes a false positive NO_ELSE_IN_WHEN in K1 since the fix is in the common code. #KT-62491 Fixed
This commit is contained in:
committed by
Space Team
parent
15d3bf5e25
commit
ac203591e5
+30
-3
@@ -19,7 +19,9 @@ package org.jetbrains.kotlin.load.java.structure.impl
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.PsiElementFactory
|
||||
import com.intellij.psi.PsiTypeParameter
|
||||
import com.intellij.psi.SyntaxTraverser
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import org.jetbrains.kotlin.asJava.KtLightClassMarker
|
||||
import org.jetbrains.kotlin.asJava.isSyntheticValuesOrValueOfMethod
|
||||
@@ -68,9 +70,18 @@ class JavaClassImpl(psiClassSource: JavaElementPsiSource<PsiClass>) : JavaClassi
|
||||
override val isSealed: Boolean
|
||||
get() = JavaElementUtil.isSealed(this)
|
||||
|
||||
override val permittedTypes: Collection<JavaClassifierType>
|
||||
get() = psi.permitsListTypes.convertIndexed { index, _ ->
|
||||
JavaClassifierTypeImpl(sourceFactory.createPermittedTypeSource(psiElementSource, index))
|
||||
override val permittedTypes: Sequence<JavaClassifierType>
|
||||
get() {
|
||||
if (!isSealed) return emptySequence()
|
||||
|
||||
val permitsListTypes = psi.permitsListTypes
|
||||
return if (permitsListTypes.isNotEmpty()) {
|
||||
permitsListTypes.convertIndexed { index, _ ->
|
||||
JavaClassifierTypeImpl(sourceFactory.createPermittedTypeSource(psiElementSource, index))
|
||||
}.asSequence()
|
||||
} else {
|
||||
lazilyComputePermittedTypesInSameFile(psiElementSource)
|
||||
}
|
||||
}
|
||||
|
||||
override val isRecord: Boolean
|
||||
@@ -163,3 +174,19 @@ class JavaClassImpl(psiClassSource: JavaElementPsiSource<PsiClass>) : JavaClassi
|
||||
private val LOGGER = Logger.getInstance(JavaClassImpl::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
private fun lazilyComputePermittedTypesInSameFile(psiElementSource: JavaElementPsiSource<PsiClass>): Sequence<JavaClassifierType> {
|
||||
return Sequence {
|
||||
// Don't capture PSI directly but only via psiElementSource
|
||||
val psi = psiElementSource.psi
|
||||
val elementFactory = PsiElementFactory.getInstance(psi.project)
|
||||
|
||||
SyntaxTraverser.psiTraverser(psi.containingFile)
|
||||
.filter(PsiClass::class.java)
|
||||
// isInheritor can lead to resolution which can cause contract violations,
|
||||
// that's why we compute it lazily only when the sequence is iterated.
|
||||
.filter { it.isInheritor(psi, /* checkDeep: */ false) }
|
||||
.map { JavaClassifierTypeImpl(psiElementSource.factory.createTypeSource(elementFactory.createType(it))) }
|
||||
.iterator()
|
||||
}
|
||||
}
|
||||
+5
-3
@@ -79,8 +79,10 @@ class BinaryJavaClass(
|
||||
|
||||
override val lightClassOriginKind: LightClassOriginKind? get() = null
|
||||
|
||||
override val isSealed: Boolean get() = permittedTypes.isNotEmpty()
|
||||
override val permittedTypes = arrayListOf<JavaClassifierType>()
|
||||
private val permittedTypesList: ArrayList<JavaClassifierType> = arrayListOf()
|
||||
override val isSealed: Boolean get() = permittedTypesList.isNotEmpty()
|
||||
override val permittedTypes: Sequence<JavaClassifierType>
|
||||
get() = permittedTypesList.asSequence()
|
||||
|
||||
override fun isFromSourceCodeInScope(scope: SearchScope): Boolean = false
|
||||
|
||||
@@ -258,6 +260,6 @@ class BinaryJavaClass(
|
||||
}
|
||||
|
||||
override fun visitPermittedSubclass(permittedSubclass: String?) {
|
||||
permittedTypes.addIfNotNull(permittedSubclass?.convertInternalNameToClassifierType())
|
||||
permittedTypesList.addIfNotNull(permittedSubclass?.convertInternalNameToClassifierType())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user