[FIR] Use toFirRegularClassSymbol instead of toFirRegular in checkers

This commit is contained in:
Ivan Kochurkin
2021-09-08 01:17:26 +03:00
committed by TeamCityServer
parent 8cdb79f969
commit 7c6326856b
18 changed files with 94 additions and 65 deletions
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.isFinal
import org.jetbrains.kotlin.fir.declarations.utils.isInterface import org.jetbrains.kotlin.fir.declarations.utils.isInterface
import org.jetbrains.kotlin.fir.dispatchReceiverTypeOrNull import org.jetbrains.kotlin.fir.dispatchReceiverTypeOrNull
import org.jetbrains.kotlin.fir.originalOrSelf import org.jetbrains.kotlin.fir.originalOrSelf
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenFunctions import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenFunctions
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenProperties import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenProperties
import org.jetbrains.kotlin.fir.symbols.SymbolInternals import org.jetbrains.kotlin.fir.symbols.SymbolInternals
@@ -79,7 +79,7 @@ object FirJvmOverridesBackwardCompatibilityHelper : FirOverridesBackwardCompatib
} }
if (!originalMember.isAbstract) { if (!originalMember.isAbstract) {
val containingClass = originalMember.containingClass()?.toFirRegularClass(context.session) val containingClass = originalMember.containingClass()?.toFirRegularClassSymbol(context.session)
if (containingClass?.isInterface == false) { if (containingClass?.isInterface == false) {
return false return false
} }
@@ -22,12 +22,12 @@ import org.jetbrains.kotlin.fir.declarations.utils.isInterface
import org.jetbrains.kotlin.fir.declarations.utils.modality import org.jetbrains.kotlin.fir.declarations.utils.modality
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.java.jvmDefaultModeState import org.jetbrains.kotlin.fir.java.jvmDefaultModeState
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenFunctions import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenFunctions
import org.jetbrains.kotlin.fir.scopes.impl.FirClassUseSiteMemberScope import org.jetbrains.kotlin.fir.scopes.impl.FirClassUseSiteMemberScope
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionCallableSymbol
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
import org.jetbrains.kotlin.name.JvmNames.JVM_DEFAULT_CLASS_ID import org.jetbrains.kotlin.name.JvmNames.JVM_DEFAULT_CLASS_ID
import org.jetbrains.kotlin.name.JvmNames.JVM_DEFAULT_NO_COMPATIBILITY_CLASS_ID import org.jetbrains.kotlin.name.JvmNames.JVM_DEFAULT_NO_COMPATIBILITY_CLASS_ID
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.isExternal
import org.jetbrains.kotlin.fir.declarations.utils.isInline import org.jetbrains.kotlin.fir.declarations.utils.isInline
import org.jetbrains.kotlin.fir.declarations.utils.isInterface import org.jetbrains.kotlin.fir.declarations.utils.isInterface
import org.jetbrains.kotlin.fir.declarations.utils.modality import org.jetbrains.kotlin.fir.declarations.utils.modality
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
object FirJvmExternalDeclarationChecker : FirBasicDeclarationChecker() { object FirJvmExternalDeclarationChecker : FirBasicDeclarationChecker() {
@@ -62,7 +62,7 @@ object FirJvmExternalDeclarationChecker : FirBasicDeclarationChecker() {
return return
} }
val containingClassSymbol = declaration.symbol.containingClass()?.toFirRegularClass(context.session) val containingClassSymbol = declaration.symbol.containingClass()?.toFirRegularClassSymbol(context.session)
if (containingClassSymbol != null) { if (containingClassSymbol != null) {
if (containingClassSymbol.isInterface) { if (containingClassSymbol.isInterface) {
reporter.reportOn(declaration.source, FirJvmErrors.EXTERNAL_DECLARATION_IN_INTERFACE, context) reporter.reportOn(declaration.source, FirJvmErrors.EXTERNAL_DECLARATION_IN_INTERFACE, context)
@@ -14,15 +14,19 @@ import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.classKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirPropertyChecker import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirPropertyChecker
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingDeclarationSymbol
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.containingClass import org.jetbrains.kotlin.fir.containingClass
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId
import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.languageVersionSettings import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
@@ -31,22 +35,18 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.JvmFieldApplicabilityProblem.*
import org.jetbrains.kotlin.load.java.JvmAbi.JVM_FIELD_ANNOTATION_CLASS_ID import org.jetbrains.kotlin.load.java.JvmAbi.JVM_FIELD_ANNOTATION_CLASS_ID
import org.jetbrains.kotlin.JvmNames.JVM_MULTIFILE_CLASS_SHORT
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingDeclarationSymbol
import org.jetbrains.kotlin.psi.stubs.elements.KtParameterElementType
object FirJvmFieldApplicabilityChecker : FirPropertyChecker() { object FirJvmFieldApplicabilityChecker : FirPropertyChecker() {
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) { override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
val annotation = declaration.getAnnotationByClassId(JVM_FIELD_ANNOTATION_CLASS_ID) ?: return val annotation = declaration.getAnnotationByClassId(JVM_FIELD_ANNOTATION_CLASS_ID) ?: return
val session = context.session val session = context.session
val containingClass = declaration.containingClass()?.toFirRegularClass(session) val containingClassSymbol = declaration.containingClass()?.toFirRegularClassSymbol(session)
val problem = when { val problem = when {
declaration.delegate != null -> DELEGATE declaration.delegate != null -> DELEGATE
!declaration.hasBackingField -> return !declaration.hasBackingField -> return
declaration.isOverridable(containingClass) -> NOT_FINAL declaration.isOverridable(containingClassSymbol) -> NOT_FINAL
Visibilities.isPrivate(declaration.visibility) -> PRIVATE Visibilities.isPrivate(declaration.visibility) -> PRIVATE
declaration.hasCustomAccessor() -> CUSTOM_ACCESSOR declaration.hasCustomAccessor() -> CUSTOM_ACCESSOR
declaration.isOverride -> OVERRIDES declaration.isOverride -> OVERRIDES
@@ -63,7 +63,7 @@ object FirJvmFieldApplicabilityChecker : FirPropertyChecker() {
} }
} }
} }
containingClass == null && isInsideJvmMultifileClassFile(context) -> containingClassSymbol == null && isInsideJvmMultifileClassFile(context) ->
TOP_LEVEL_PROPERTY_OF_MULTIFILE_FACADE TOP_LEVEL_PROPERTY_OF_MULTIFILE_FACADE
declaration.returnTypeRef.isInlineClassThatRequiresMangling(session) -> RETURN_TYPE_IS_INLINE_CLASS declaration.returnTypeRef.isInlineClassThatRequiresMangling(session) -> RETURN_TYPE_IS_INLINE_CLASS
else -> return else -> return
@@ -89,7 +89,7 @@ object FirJvmFieldApplicabilityChecker : FirPropertyChecker() {
return this.classId.relativeClassName.asString() == StandardNames.RESULT_FQ_NAME.asString() return this.classId.relativeClassName.asString() == StandardNames.RESULT_FQ_NAME.asString()
} }
private fun FirProperty.isOverridable(containingClass: FirRegularClass?): Boolean { private fun FirProperty.isOverridable(containingClass: FirRegularClassSymbol?): Boolean {
return visibility != Visibilities.Private && modality != Modality.FINAL && return visibility != Visibilities.Private && modality != Modality.FINAL &&
containingClass?.isFinal != true containingClass?.isFinal != true
} }
@@ -104,7 +104,7 @@ object FirJvmFieldApplicabilityChecker : FirPropertyChecker() {
return false return false
} }
val outerClassKind = (getContainingDeclarationSymbol(session) as? FirRegularClass)?.classKind val outerClassKind = getContainingDeclarationSymbol(session)?.classKind
return outerClassKind == ClassKind.INTERFACE || outerClassKind == ClassKind.ANNOTATION_CLASS return outerClassKind == ClassKind.INTERFACE || outerClassKind == ClassKind.ANNOTATION_CLASS
} }
@@ -21,11 +21,8 @@ import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyExpressionBlock import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyExpressionBlock
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.resolve.SessionHolder import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType
import org.jetbrains.kotlin.fir.resolve.symbolProvider
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.impl.multipleDelegatesWithTheSameSignature import org.jetbrains.kotlin.fir.scopes.impl.multipleDelegatesWithTheSameSignature
@@ -135,6 +132,21 @@ fun FirClassLikeSymbol<*>.outerClassSymbol(context: CheckerContext): FirClassLik
return context.session.symbolProvider.getClassLikeSymbolByClassId(outerClassId) return context.session.symbolProvider.getClassLikeSymbolByClassId(outerClassId)
} }
@OptIn(SymbolInternals::class)
fun FirClassSymbol<*>.getContainingDeclarationSymbol(session: FirSession): FirClassLikeSymbol<*>? {
if (isLocal) {
return (this as FirRegularClassSymbol).fir.containingClassForLocalAttr?.toFirRegularClassSymbol(session)
} else {
val parentId = classId.relativeClassName.parent()
if (!parentId.isRoot) {
val containingDeclarationId = ClassId(classId.packageFqName, parentId, false)
return session.symbolProvider.getClassLikeSymbolByClassId(containingDeclarationId)
}
}
return null
}
/** /**
* Returns the FirClassLikeDeclaration that the * Returns the FirClassLikeDeclaration that the
* sequence of FirTypeAlias'es points to starting * sequence of FirTypeAlias'es points to starting
@@ -171,7 +183,7 @@ fun CheckerContext.findClosestClassOrObject(): FirClass? {
* Returns the list of functions that overridden by given * Returns the list of functions that overridden by given
*/ */
fun FirSimpleFunction.overriddenFunctions( fun FirSimpleFunction.overriddenFunctions(
containingClass: FirClass, containingClass: FirClassSymbol<*>,
context: CheckerContext context: CheckerContext
): List<FirFunctionSymbol<*>> { ): List<FirFunctionSymbol<*>> {
val firTypeScope = containingClass.unsubstitutedScope( val firTypeScope = containingClass.unsubstitutedScope(
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.containingClass import org.jetbrains.kotlin.fir.containingClass
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.utils.isOperator import org.jetbrains.kotlin.fir.declarations.utils.isOperator
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
import org.jetbrains.kotlin.fir.typeContext import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
@@ -185,8 +185,8 @@ private object OperatorFunctionChecks {
EQUALS, EQUALS,
member, member,
Checks.full("must override ''equals()'' in Any") { ctx, function -> Checks.full("must override ''equals()'' in Any") { ctx, function ->
val containingClass = function.containingClass()?.toFirRegularClass(ctx.session) ?: return@full true val containingClassSymbol = function.containingClass()?.toFirRegularClassSymbol(ctx.session) ?: return@full true
function.overriddenFunctions(containingClass, ctx).any { function.overriddenFunctions(containingClassSymbol, ctx).any {
it.containingClass()?.classId?.asSingleFqName() == StandardNames.FqNames.any.toSafe() it.containingClass()?.classId?.asSingleFqName() == StandardNames.FqNames.any.toSafe()
} }
} }
@@ -19,7 +19,7 @@ import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirOperation import org.jetbrains.kotlin.fir.expressions.FirOperation
import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
import org.jetbrains.kotlin.fir.typeContext import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
@@ -106,8 +106,8 @@ object FirEqualityCompatibilityChecker : FirEqualityOperatorCallChecker() {
context: CheckerContext context: CheckerContext
): Boolean { ): Boolean {
if (isEnum) return true if (isEnum) return true
val firRegularClass = (this as? ConeClassLikeType)?.lookupTag?.toFirRegularClass(context.session) ?: return false val firRegularClassSymbol = (this as? ConeClassLikeType)?.lookupTag?.toFirRegularClassSymbol(context.session) ?: return false
return firRegularClass.isEnumClass return firRegularClassSymbol.isEnumClass
} }
private fun checkSensibleness( private fun checkSensibleness(
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenFunctions import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenFunctions
@@ -132,7 +132,7 @@ object FirOptInUsageBaseChecker {
val annotationType = annotation.annotationTypeRef.coneTypeSafe<ConeClassLikeType>() val annotationType = annotation.annotationTypeRef.coneTypeSafe<ConeClassLikeType>()
if (annotation.useSiteTarget != AnnotationUseSiteTarget.PROPERTY_SETTER || fromSetter) { if (annotation.useSiteTarget != AnnotationUseSiteTarget.PROPERTY_SETTER || fromSetter) {
result.addIfNotNull( result.addIfNotNull(
annotationType?.lookupTag?.toFirRegularClass( annotationType?.lookupTag?.toFirRegularClassSymbol(
session session
)?.loadExperimentalityForMarkerAnnotation() )?.loadExperimentalityForMarkerAnnotation()
) )
@@ -15,13 +15,15 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.getChild import org.jetbrains.kotlin.fir.analysis.getChild
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isSuspend import org.jetbrains.kotlin.fir.declarations.utils.isSuspend
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReference import org.jetbrains.kotlin.fir.references.FirResolvedCallableReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
@@ -145,25 +147,25 @@ object FirSuspendCallChecker : FirQualifiedAccessExpressionChecker() {
context: CheckerContext context: CheckerContext
): Boolean { ): Boolean {
val session = context.session val session = context.session
val enclosingSuspendFunctionDispatchReceiverOwner = val enclosingSuspendFunctionDispatchReceiverOwnerSymbol =
(enclosingSuspendFunction.dispatchReceiverType as? ConeClassLikeType)?.lookupTag?.toFirRegularClass(session) (enclosingSuspendFunction.dispatchReceiverType as? ConeClassLikeType)?.lookupTag?.toFirRegularClassSymbol(session)
val enclosingSuspendFunctionExtensionReceiverOwner = enclosingSuspendFunction.takeIf { it.receiverTypeRef != null } val enclosingSuspendFunctionExtensionReceiverOwnerSymbol = enclosingSuspendFunction.takeIf { it.receiverTypeRef != null }?.symbol
val dispatchReceiverExpression = expression.dispatchReceiver.takeIf { it !is FirNoReceiverExpression } val dispatchReceiverExpression = expression.dispatchReceiver.takeIf { it !is FirNoReceiverExpression }
val extensionReceiverExpression = expression.extensionReceiver.takeIf { it !is FirNoReceiverExpression } val extensionReceiverExpression = expression.extensionReceiver.takeIf { it !is FirNoReceiverExpression }
for (receiverExpression in listOfNotNull(dispatchReceiverExpression, extensionReceiverExpression)) { for (receiverExpression in listOfNotNull(dispatchReceiverExpression, extensionReceiverExpression)) {
if (!receiverExpression.typeRef.coneType.isRestrictSuspensionReceiver(session)) continue if (!receiverExpression.typeRef.coneType.isRestrictSuspensionReceiver(session)) continue
if (sameInstanceOfReceiver(receiverExpression, enclosingSuspendFunctionDispatchReceiverOwner)) continue if (sameInstanceOfReceiver(receiverExpression, enclosingSuspendFunctionDispatchReceiverOwnerSymbol)) continue
if (sameInstanceOfReceiver(receiverExpression, enclosingSuspendFunctionExtensionReceiverOwner)) continue if (sameInstanceOfReceiver(receiverExpression, enclosingSuspendFunctionExtensionReceiverOwnerSymbol)) continue
return false return false
} }
if (enclosingSuspendFunctionExtensionReceiverOwner?.receiverTypeRef?.coneType?.isRestrictSuspensionReceiver(session) != true) { if (enclosingSuspendFunctionExtensionReceiverOwnerSymbol?.resolvedReceiverTypeRef?.coneType?.isRestrictSuspensionReceiver(session) != true) {
return true return true
} }
if (sameInstanceOfReceiver(dispatchReceiverExpression, enclosingSuspendFunctionExtensionReceiverOwner)) { if (sameInstanceOfReceiver(dispatchReceiverExpression, enclosingSuspendFunctionExtensionReceiverOwnerSymbol)) {
return true return true
} }
if (sameInstanceOfReceiver(extensionReceiverExpression, enclosingSuspendFunctionExtensionReceiverOwner)) { if (sameInstanceOfReceiver(extensionReceiverExpression, enclosingSuspendFunctionExtensionReceiverOwnerSymbol)) {
if (calledDeclarationSymbol.resolvedReceiverTypeRef?.coneType?.isRestrictSuspensionReceiver(session) == true) { if (calledDeclarationSymbol.resolvedReceiverTypeRef?.coneType?.isRestrictSuspensionReceiver(session) == true) {
return true return true
} }
@@ -174,11 +176,11 @@ object FirSuspendCallChecker : FirQualifiedAccessExpressionChecker() {
private fun ConeKotlinType.isRestrictSuspensionReceiver(session: FirSession): Boolean { private fun ConeKotlinType.isRestrictSuspensionReceiver(session: FirSession): Boolean {
when (this) { when (this) {
is ConeClassLikeType -> { is ConeClassLikeType -> {
val regularClass = fullyExpandedType(session).lookupTag.toFirRegularClass(session) ?: return false val regularClassSymbol = fullyExpandedType(session).lookupTag.toFirRegularClassSymbol(session) ?: return false
if (regularClass.hasAnnotation(RESTRICTS_SUSPENSION_CLASS_ID)) { if (regularClassSymbol.getAnnotationByClassId(RESTRICTS_SUSPENSION_CLASS_ID) != null) {
return true return true
} }
return regularClass.superTypeRefs.any { it.coneType.isRestrictSuspensionReceiver(session) } return regularClassSymbol.superConeTypes.any { it.isRestrictSuspensionReceiver(session) }
} }
is ConeTypeParameterType -> { is ConeTypeParameterType -> {
return lookupTag.typeParameterSymbol.resolvedBounds.any { it.coneType.isRestrictSuspensionReceiver(session) } return lookupTag.typeParameterSymbol.resolvedBounds.any { it.coneType.isRestrictSuspensionReceiver(session) }
@@ -187,10 +189,13 @@ object FirSuspendCallChecker : FirQualifiedAccessExpressionChecker() {
} }
} }
private fun sameInstanceOfReceiver(useSiteReceiverExpression: FirExpression?, declarationSiteReceiverOwner: FirDeclaration?): Boolean { private fun sameInstanceOfReceiver(
if (declarationSiteReceiverOwner == null || useSiteReceiverExpression == null) return false useSiteReceiverExpression: FirExpression?,
declarationSiteReceiverOwnerSymbol: FirBasedSymbol<*>?
): Boolean {
if (declarationSiteReceiverOwnerSymbol == null || useSiteReceiverExpression == null) return false
if (useSiteReceiverExpression is FirThisReceiverExpression) { if (useSiteReceiverExpression is FirThisReceiverExpression) {
return useSiteReceiverExpression.calleeReference.boundSymbol == declarationSiteReceiverOwner.symbol return useSiteReceiverExpression.calleeReference.boundSymbol == declarationSiteReceiverOwnerSymbol
} }
return false return false
} }
@@ -95,8 +95,8 @@ object RedundantVisibilityModifierSyntaxChecker : FirDeclarationSyntaxChecker<Fi
} }
private fun findFunctionVisibility(function: FirSimpleFunction, context: CheckerContext): Visibility { private fun findFunctionVisibility(function: FirSimpleFunction, context: CheckerContext): Visibility {
val currentClass = context.findClosestClassOrObject() ?: return Visibilities.Unknown val currentClassSymbol = context.findClosestClassOrObject()?.symbol ?: return Visibilities.Unknown
val overriddenFunctions = function.overriddenFunctions(currentClass, context) val overriddenFunctions = function.overriddenFunctions(currentClassSymbol, context)
var visibility: Visibility = Visibilities.Private var visibility: Visibility = Visibilities.Private
for (func in overriddenFunctions) { for (func in overriddenFunctions) {
val currentVisibility = func.visibility val currentVisibility = func.visibility
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.firProvider import org.jetbrains.kotlin.fir.resolve.firProvider
import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
import org.jetbrains.kotlin.fir.serialization.FirElementSerializer import org.jetbrains.kotlin.fir.serialization.FirElementSerializer
import org.jetbrains.kotlin.fir.serialization.FirSerializerExtension import org.jetbrains.kotlin.fir.serialization.FirSerializerExtension
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
@@ -260,14 +260,14 @@ class FirJvmSerializerExtension(
private fun FirProperty.isJvmFieldPropertyInInterfaceCompanion(): Boolean { private fun FirProperty.isJvmFieldPropertyInInterfaceCompanion(): Boolean {
if (!hasJvmFieldAnnotation) return false if (!hasJvmFieldAnnotation) return false
val container = (dispatchReceiverType as? ConeClassLikeType)?.lookupTag?.toFirRegularClass(session) val containerSymbol = (dispatchReceiverType as? ConeClassLikeType)?.lookupTag?.toFirRegularClassSymbol(session)
// Note: companions are anyway forbidden in local classes // Note: companions are anyway forbidden in local classes
if (container == null || !container.isCompanion || container.isLocal) { if (containerSymbol == null || !containerSymbol.isCompanion || containerSymbol.isLocal) {
return false return false
} }
val grandParent = val grandParent =
container.classId.outerClassId?.let { containerSymbol.classId.outerClassId?.let {
session.firProvider.getFirClassifierByFqName(it) as? FirRegularClass session.firProvider.getFirClassifierByFqName(it) as? FirRegularClass
} }
return grandParent != null && return grandParent != null &&
@@ -13,9 +13,10 @@ import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.java.enhancement.readOnlyToMutable import org.jetbrains.kotlin.fir.java.enhancement.readOnlyToMutable
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.typeContext import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
@@ -166,19 +167,19 @@ private fun JavaClassifierType.toConeKotlinTypeForFlexibleBound(
// When converting type parameter bounds we should not attempt to load any classes, as this may trigger // When converting type parameter bounds we should not attempt to load any classes, as this may trigger
// enhancement of type parameter bounds on some other class that depends on this one. Also, in case of raw // enhancement of type parameter bounds on some other class that depends on this one. Also, in case of raw
// types specifically there could be an infinite recursion on the type parameter itself. // types specifically there could be an infinite recursion on the type parameter itself.
val typeParameters = lookupTag.takeIf { mode != FirJavaTypeConversionMode.TYPE_PARAMETER_BOUND } val typeParameterSymbols = lookupTag.takeIf { mode != FirJavaTypeConversionMode.TYPE_PARAMETER_BOUND }
?.toFirRegularClass(session)?.typeParameters ?.toFirRegularClassSymbol(session)?.typeParameterSymbols
val mappedTypeArguments = when { val mappedTypeArguments = when {
isRaw -> isRaw ->
// Given `C<T : X>`, `C` -> `C<X>..C<*>?`. // Given `C<T : X>`, `C` -> `C<X>..C<*>?`.
typeParameters.takeIf { lowerBound == null }?.eraseToUpperBounds(session) typeParameterSymbols.takeIf { lowerBound == null }?.eraseToUpperBounds(session)
?: Array(classifier.typeParameters.size) { ConeStarProjection } ?: Array(classifier.typeParameters.size) { ConeStarProjection }
lookupTag != lowerBound?.lookupTag -> lookupTag != lowerBound?.lookupTag ->
Array(typeArguments.size) { index -> Array(typeArguments.size) { index ->
// TODO: check this // TODO: check this
val newMode = if (mode == FirJavaTypeConversionMode.ANNOTATION_MEMBER) FirJavaTypeConversionMode.DEFAULT else mode val newMode = if (mode == FirJavaTypeConversionMode.ANNOTATION_MEMBER) FirJavaTypeConversionMode.DEFAULT else mode
val argument = typeArguments[index] val argument = typeArguments[index]
val variance = typeParameters?.getOrNull(index)?.symbol?.fir?.variance ?: Variance.INVARIANT val variance = typeParameterSymbols?.getOrNull(index)?.fir?.variance ?: Variance.INVARIANT
argument.toConeTypeProjection(session, javaTypeParameterStack, variance, newMode) argument.toConeTypeProjection(session, javaTypeParameterStack, variance, newMode)
} }
else -> lowerBound.typeArguments else -> lowerBound.typeArguments
@@ -211,15 +212,15 @@ private fun JavaClassifierType.argumentsMakeSenseOnlyForMutableContainer(
if (!typeArguments.lastOrNull().isSuperWildcard()) return false if (!typeArguments.lastOrNull().isSuperWildcard()) return false
val mutableLastParameterVariance = val mutableLastParameterVariance =
mutableClassId.toLookupTag().toFirRegularClass(session)?.typeParameters?.lastOrNull()?.symbol?.fir?.variance mutableClassId.toLookupTag().toFirRegularClassSymbol(session)?.typeParameterSymbols?.lastOrNull()?.variance
?: return false ?: return false
return mutableLastParameterVariance != Variance.OUT_VARIANCE return mutableLastParameterVariance != Variance.OUT_VARIANCE
} }
private fun List<FirTypeParameterRef>.eraseToUpperBounds(session: FirSession): Array<ConeTypeProjection> { private fun List<FirTypeParameterSymbol>.eraseToUpperBounds(session: FirSession): Array<ConeTypeProjection> {
val cache = mutableMapOf<FirTypeParameter, ConeKotlinType>() val cache = mutableMapOf<FirTypeParameter, ConeKotlinType>()
return Array(size) { index -> this[index].symbol.fir.eraseToUpperBound(session, cache) } return Array(size) { index -> this[index].fir.eraseToUpperBound(session, cache) }
} }
private fun FirTypeParameter.eraseToUpperBound(session: FirSession, cache: MutableMap<FirTypeParameter, ConeKotlinType>): ConeKotlinType { private fun FirTypeParameter.eraseToUpperBound(session: FirSession, cache: MutableMap<FirTypeParameter, ConeKotlinType>): ConeKotlinType {
@@ -39,15 +39,19 @@ fun ConeClassLikeLookupTag.toSymbolOrError(useSiteSession: FirSession): FirClass
toSymbol(useSiteSession) toSymbol(useSiteSession)
?: error("Class symbol with classId $classId was not found") ?: error("Class symbol with classId $classId was not found")
@OptIn(LookupTagInternals::class)
fun ConeClassLikeLookupTag.toFirRegularClass(session: FirSession): FirRegularClass? = fun ConeClassLikeLookupTag.toFirRegularClassSymbol(session: FirSession): FirRegularClassSymbol? =
session.symbolProvider.getSymbolByLookupTag(this)?.fir as? FirRegularClass session.symbolProvider.getSymbolByLookupTag(this) as? FirRegularClassSymbol
@OptIn(LookupTagInternals::class) @OptIn(LookupTagInternals::class)
fun ConeClassLikeLookupTagImpl.bindSymbolToLookupTag(session: FirSession, symbol: FirClassLikeSymbol<*>?) { fun ConeClassLikeLookupTagImpl.bindSymbolToLookupTag(session: FirSession, symbol: FirClassLikeSymbol<*>?) {
boundSymbol = WeakPair(session, symbol) boundSymbol = WeakPair(session, symbol)
} }
@LookupTagInternals
fun ConeClassLikeLookupTag.toFirRegularClass(session: FirSession): FirRegularClass? =
session.symbolProvider.getSymbolByLookupTag(this)?.fir as? FirRegularClass
fun FirSymbolProvider.getSymbolByLookupTag(lookupTag: ConeClassifierLookupTag): FirClassifierSymbol<*>? { fun FirSymbolProvider.getSymbolByLookupTag(lookupTag: ConeClassifierLookupTag): FirClassifierSymbol<*>? {
return lookupTag.toSymbol(session) return lookupTag.toSymbol(session)
} }
@@ -505,6 +505,7 @@ fun FirRegularClass.getActualTypeParametersCount(session: FirSession): Int {
fun FirClassLikeDeclaration.getContainingDeclaration(session: FirSession): FirClassLikeDeclaration? { fun FirClassLikeDeclaration.getContainingDeclaration(session: FirSession): FirClassLikeDeclaration? {
if (isLocal) { if (isLocal) {
@OptIn(LookupTagInternals::class)
return (this as? FirRegularClass)?.containingClassForLocalAttr?.toFirRegularClass(session) return (this as? FirRegularClass)?.containingClassForLocalAttr?.toFirRegularClass(session)
} else { } else {
val classId = symbol.classId val classId = symbol.classId
@@ -69,6 +69,7 @@ class FirSamResolverImpl(
} }
private fun getFunctionTypeForPossibleSamType(type: ConeClassLikeType): ConeLookupTagBasedType? { private fun getFunctionTypeForPossibleSamType(type: ConeClassLikeType): ConeLookupTagBasedType? {
@OptIn(LookupTagInternals::class)
val firRegularClass = type.lookupTag.toFirRegularClass(session) ?: return null val firRegularClass = type.lookupTag.toFirRegularClass(session) ?: return null
val unsubstitutedFunctionType = resolveFunctionTypeIfSamInterface(firRegularClass) ?: return null val unsubstitutedFunctionType = resolveFunctionTypeIfSamInterface(firRegularClass) ?: return null
@@ -16,7 +16,7 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.references.* import org.jetbrains.kotlin.fir.references.*
import org.jetbrains.kotlin.fir.resolve.defaultType import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
@@ -844,7 +844,7 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
return when (val fir = this.fir) { return when (val fir = this.fir) {
is FirConstructor -> fir.returnTypeRef.coneType.isLocal() is FirConstructor -> fir.returnTypeRef.coneType.isLocal()
is FirCallableDeclaration -> { is FirCallableDeclaration -> {
fir.dispatchReceiverClassOrNull()?.toFirRegularClass(session)?.isLocal ?: false fir.dispatchReceiverClassOrNull()?.toFirRegularClassSymbol(session)?.isLocal ?: false
} }
else -> false else -> false
} }
@@ -852,7 +852,7 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
private fun ConeKotlinType.isLocal(): Boolean { private fun ConeKotlinType.isLocal(): Boolean {
if (this !is ConeClassLikeType) return false if (this !is ConeClassLikeType) return false
return this.lookupTag.toFirRegularClass(session)?.isLocal == true return this.lookupTag.toFirRegularClassSymbol(session)?.isLocal == true
} }
// id == packageName + className // id == packageName + className
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.renderWithType import org.jetbrains.kotlin.fir.renderWithType
import org.jetbrains.kotlin.fir.resolve.firProvider import org.jetbrains.kotlin.fir.resolve.firProvider
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass import org.jetbrains.kotlin.fir.resolve.toFirRegularClass
import org.jetbrains.kotlin.fir.symbols.impl.LookupTagInternals
import org.jetbrains.kotlin.idea.fir.low.level.api.util.getContainingFile import org.jetbrains.kotlin.idea.fir.low.level.api.util.getContainingFile
class FirDeclarationDesignationWithFile( class FirDeclarationDesignationWithFile(
@@ -63,6 +64,7 @@ private fun collectDesignationPath(declaration: FirDeclaration): List<FirDeclara
is FirSimpleFunction, is FirProperty, is FirField, is FirConstructor -> { is FirSimpleFunction, is FirProperty, is FirField, is FirConstructor -> {
val klass = declaration.containingClass() ?: return emptyList() val klass = declaration.containingClass() ?: return emptyList()
if (klass.classId.isLocal) return null if (klass.classId.isLocal) return null
@OptIn(LookupTagInternals::class)
klass.toFirRegularClass(declaration.moduleData.session) klass.toFirRegularClass(declaration.moduleData.session)
} }
else -> return null else -> return null
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.resolve.inference.*
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass import org.jetbrains.kotlin.fir.resolve.toFirRegularClass
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.LookupTagInternals
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.idea.fir.low.level.api.api.tryCollectDesignation import org.jetbrains.kotlin.idea.fir.low.level.api.api.tryCollectDesignation
import org.jetbrains.kotlin.idea.frontend.api.components.KtTypeRendererOptions import org.jetbrains.kotlin.idea.frontend.api.components.KtTypeRendererOptions
@@ -183,6 +184,7 @@ internal class ConeTypeIdeRenderer(
require(isLocal) require(isLocal)
var containingClassLookUp = containingClassForLocal() var containingClassLookUp = containingClassForLocal()
val designation = mutableListOf<FirClassLikeDeclaration>(this) val designation = mutableListOf<FirClassLikeDeclaration>(this)
@OptIn(LookupTagInternals::class)
while (containingClassLookUp != null && containingClassLookUp.classId.isLocal) { while (containingClassLookUp != null && containingClassLookUp.classId.isLocal) {
val currentClass = containingClassLookUp.toFirRegularClass(moduleData.session) ?: break val currentClass = containingClassLookUp.toFirRegularClass(moduleData.session) ?: break
designation.add(currentClass) designation.add(currentClass)
@@ -192,6 +194,7 @@ internal class ConeTypeIdeRenderer(
} }
private fun collectDesignationPathForLocal(declaration: FirDeclaration): List<FirDeclaration>? { private fun collectDesignationPathForLocal(declaration: FirDeclaration): List<FirDeclaration>? {
@OptIn(LookupTagInternals::class)
val containingClass = when (declaration) { val containingClass = when (declaration) {
is FirCallableDeclaration -> declaration.containingClass()?.toFirRegularClass(declaration.moduleData.session) is FirCallableDeclaration -> declaration.containingClass()?.toFirRegularClass(declaration.moduleData.session)
is FirAnonymousObject -> return listOf(declaration) is FirAnonymousObject -> return listOf(declaration)