[Analysis API] Treat inapplicable declarations safely (KTIJ-23458)
Make 'getClassOrObjectSymbol()' and 'getNamedClassOrObjectSymbol()' return 'null' for inapplicable PSI declarations.
This commit is contained in:
+4
-2
@@ -87,8 +87,10 @@ internal class KtFe10SymbolProvider(
|
||||
return KtFe10PsiAnonymousObjectSymbol(psi.objectDeclaration, analysisContext)
|
||||
}
|
||||
|
||||
override fun getClassOrObjectSymbol(psi: KtClassOrObject): KtClassOrObjectSymbol {
|
||||
return if (psi is KtObjectDeclaration && psi.isObjectLiteral()) {
|
||||
override fun getClassOrObjectSymbol(psi: KtClassOrObject): KtClassOrObjectSymbol? {
|
||||
return if (psi is KtEnumEntry) {
|
||||
null
|
||||
} else if (psi is KtObjectDeclaration && psi.isObjectLiteral()) {
|
||||
KtFe10PsiAnonymousObjectSymbol(psi, analysisContext)
|
||||
} else {
|
||||
KtFe10PsiNamedClassOrObjectSymbol(psi, analysisContext)
|
||||
|
||||
+14
-7
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.withPsiEntry
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isObjectLiteral
|
||||
|
||||
internal class KtFirSymbolProvider(
|
||||
override val analysisSession: KtFirAnalysisSession,
|
||||
@@ -113,16 +114,22 @@ internal class KtFirSymbolProvider(
|
||||
)
|
||||
}
|
||||
|
||||
override fun getClassOrObjectSymbol(psi: KtClassOrObject): KtClassOrObjectSymbol {
|
||||
val firClass = psi.resolveToFirClassLikeSymbol()
|
||||
return firSymbolBuilder.classifierBuilder.buildClassOrObjectSymbol(firClass)
|
||||
override fun getClassOrObjectSymbol(psi: KtClassOrObject): KtClassOrObjectSymbol? {
|
||||
if (psi is KtEnumEntry) {
|
||||
return null
|
||||
}
|
||||
|
||||
val firSymbol = psi.resolveToFirClassLikeSymbol()
|
||||
return firSymbolBuilder.classifierBuilder.buildClassOrObjectSymbol(firSymbol)
|
||||
}
|
||||
|
||||
override fun getNamedClassOrObjectSymbol(psi: KtClassOrObject): KtNamedClassOrObjectSymbol? {
|
||||
require(psi !is KtObjectDeclaration || psi.parent !is KtObjectLiteralExpression)
|
||||
// A KtClassOrObject may also map to an FirEnumEntry. Hence, we need to return null in this case.
|
||||
if (psi is KtEnumEntry) return null
|
||||
return firSymbolBuilder.classifierBuilder.buildNamedClassOrObjectSymbol(psi.resolveToFirClassLikeSymbol() as FirRegularClassSymbol)
|
||||
if (psi is KtEnumEntry || psi.isObjectLiteral()) {
|
||||
return null
|
||||
}
|
||||
|
||||
val firSymbol = psi.resolveToFirClassLikeSymbol() as FirRegularClassSymbol
|
||||
return firSymbolBuilder.classifierBuilder.buildNamedClassOrObjectSymbol(firSymbol)
|
||||
}
|
||||
|
||||
private fun KtClassOrObject.resolveToFirClassLikeSymbol(): FirClassSymbol<*> {
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ abstract class AbstractContainingDeclarationProviderByDelegatedMemberScopeTest :
|
||||
val declaration = testServices.expressionMarkerProvider.getElementOfTypeAtCaret<KtClassOrObject>(ktFile)
|
||||
|
||||
val memberToContainingClass = analyseForTest(declaration) {
|
||||
val symbol = declaration.getClassOrObjectSymbol()
|
||||
val symbol = declaration.getClassOrObjectSymbol()!!
|
||||
renderScopeWithParentDeclarations(symbol.getDelegatedMemberScope())
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ abstract class AbstractContainingDeclarationProviderByMemberScopeTest : Abstract
|
||||
val declaration = testServices.expressionMarkerProvider.getElementOfTypeAtCaret<KtClassOrObject>(ktFile)
|
||||
|
||||
val memberToContainingClass = analyseForTest(declaration) {
|
||||
val symbol = declaration.getClassOrObjectSymbol()
|
||||
val symbol = declaration.getClassOrObjectSymbol()!!
|
||||
renderScopeWithParentDeclarations(symbol.getMemberScope())
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -21,8 +21,8 @@ abstract class AbstractIsSubclassOfTest : AbstractAnalysisApiBasedSingleModuleTe
|
||||
|
||||
val actual = executeOnPooledThreadInReadAction {
|
||||
analyseForTest(subClass) {
|
||||
val subClassSymbol = subClass.getClassOrObjectSymbol()
|
||||
val superClassSymbol = superClass.getClassOrObjectSymbol()
|
||||
val subClassSymbol = subClass.getClassOrObjectSymbol()!!
|
||||
val superClassSymbol = superClass.getClassOrObjectSymbol()!!
|
||||
|
||||
val isSubClass = subClassSymbol.isSubClassOf(superClassSymbol)
|
||||
val isDirectSubClass = subClassSymbol.isDirectSubClassOf(superClassSymbol)
|
||||
|
||||
+5
-4
@@ -26,7 +26,7 @@ public abstract class KtSymbolProvider : KtAnalysisSessionComponent() {
|
||||
is KtProperty -> getVariableSymbol(psi)
|
||||
is KtClassOrObject -> {
|
||||
val literalExpression = (psi as? KtObjectDeclaration)?.parent as? KtObjectLiteralExpression
|
||||
literalExpression?.let(::getAnonymousObjectSymbol) ?: getClassOrObjectSymbol(psi)
|
||||
literalExpression?.let(::getAnonymousObjectSymbol) ?: getClassOrObjectSymbol(psi)!!
|
||||
}
|
||||
is KtPropertyAccessor -> getPropertyAccessorSymbol(psi)
|
||||
is KtClassInitializer -> getClassInitializerSymbol(psi)
|
||||
@@ -45,7 +45,7 @@ public abstract class KtSymbolProvider : KtAnalysisSessionComponent() {
|
||||
public abstract fun getAnonymousFunctionSymbol(psi: KtFunctionLiteral): KtAnonymousFunctionSymbol
|
||||
public abstract fun getVariableSymbol(psi: KtProperty): KtVariableSymbol
|
||||
public abstract fun getAnonymousObjectSymbol(psi: KtObjectLiteralExpression): KtAnonymousObjectSymbol
|
||||
public abstract fun getClassOrObjectSymbol(psi: KtClassOrObject): KtClassOrObjectSymbol
|
||||
public abstract fun getClassOrObjectSymbol(psi: KtClassOrObject): KtClassOrObjectSymbol?
|
||||
public abstract fun getNamedClassOrObjectSymbol(psi: KtClassOrObject): KtNamedClassOrObjectSymbol?
|
||||
public abstract fun getPropertyAccessorSymbol(psi: KtPropertyAccessor): KtPropertyAccessorSymbol
|
||||
public abstract fun getClassInitializerSymbol(psi: KtClassInitializer): KtClassInitializerSymbol
|
||||
@@ -115,10 +115,11 @@ public interface KtSymbolProviderMixIn : KtAnalysisSessionMixIn {
|
||||
public fun KtObjectLiteralExpression.getAnonymousObjectSymbol(): KtAnonymousObjectSymbol =
|
||||
withValidityAssertion { analysisSession.symbolProvider.getAnonymousObjectSymbol(this) }
|
||||
|
||||
public fun KtClassOrObject.getClassOrObjectSymbol(): KtClassOrObjectSymbol =
|
||||
/** Returns a symbol for a given [KtClassOrObject]. Returns `null` for `KtEnumEntry` declarations. */
|
||||
public fun KtClassOrObject.getClassOrObjectSymbol(): KtClassOrObjectSymbol? =
|
||||
withValidityAssertion { analysisSession.symbolProvider.getClassOrObjectSymbol(this) }
|
||||
|
||||
/** Gets the corresponding class or object symbol or null if the given [KtClassOrObject] is an enum entry. */
|
||||
/** Returns a symbol for a given named [KtClassOrObject]. Returns `null` for `KtEnumEntry` declarations and object literals. */
|
||||
public fun KtClassOrObject.getNamedClassOrObjectSymbol(): KtNamedClassOrObjectSymbol? =
|
||||
withValidityAssertion { analysisSession.symbolProvider.getNamedClassOrObjectSymbol(this) }
|
||||
|
||||
|
||||
+3
-3
@@ -69,7 +69,7 @@ internal fun createSymbolLightClassNoCache(classOrObject: KtClassOrObject): KtLi
|
||||
|
||||
else -> {
|
||||
analyzeForLightClasses(classOrObject) {
|
||||
classOrObject.getClassOrObjectSymbol().createLightClassNoCache(classOrObject.manager)
|
||||
classOrObject.getClassOrObjectSymbol()?.createLightClassNoCache(classOrObject.manager)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -480,7 +480,7 @@ internal fun KtClassOrObject.checkIsInheritor(superClassOrigin: KtClassOrObject,
|
||||
return false
|
||||
}
|
||||
|
||||
val superClassSymbol = superClassOrigin.getClassOrObjectSymbol()
|
||||
val superClassSymbol = superClassOrigin.getClassOrObjectSymbol() ?: return false
|
||||
|
||||
when (this) {
|
||||
is KtEnumEntry -> {
|
||||
@@ -498,7 +498,7 @@ internal fun KtClassOrObject.checkIsInheritor(superClassOrigin: KtClassOrObject,
|
||||
else -> {
|
||||
val subClassSymbol = this.getClassOrObjectSymbol()
|
||||
|
||||
if (subClassSymbol == superClassSymbol) return false
|
||||
if (subClassSymbol == null || subClassSymbol == superClassSymbol) return false
|
||||
|
||||
return if (checkDeep) {
|
||||
subClassSymbol.isSubClassOf(superClassSymbol)
|
||||
|
||||
Reference in New Issue
Block a user