[LL FIR] KTIJ-24895 Record compound assignments with error names
- If the callee reference in a desugared compound assignment was an error reference, the compound assignment wasn't cached by `FirElementsRecorder`. This led to KTIJ-24895 (see the issue for more details). - The solution falls back on the compound assignment's source to decide `isSourceForCompoundAccess`, as an operation name can be reconstructed from the PSI. ^KTIJ-24895 fixed
This commit is contained in:
committed by
Space Team
parent
d14a55d775
commit
9a3eece944
+20
-2
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.*
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.DuplicatedFirSourceElementsException
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.isErrorElement
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.builder.toFirOperationOrNull
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildConstExpression
|
||||
import org.jetbrains.kotlin.fir.references.*
|
||||
@@ -19,6 +20,7 @@ import org.jetbrains.kotlin.fir.types.FirUserTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType
|
||||
import org.jetbrains.kotlin.types.ConstantValueKind
|
||||
@@ -147,17 +149,33 @@ internal open class FirElementsRecorder : FirVisitor<Unit, MutableMap<KtElement,
|
||||
private fun FirElement.isReadInCompoundCall(): Boolean {
|
||||
if (this is FirPropertyAccessExpression) return true
|
||||
if (this !is FirFunctionCall) return false
|
||||
val name = (calleeReference as? FirResolvedNamedReference)?.name
|
||||
val name = (calleeReference as? FirResolvedNamedReference)?.name ?: getFallbackCompoundCalleeName()
|
||||
return name == OperatorNameConventions.GET
|
||||
}
|
||||
|
||||
private fun FirElement.isWriteInCompoundCall(): Boolean {
|
||||
if (this is FirVariableAssignment) return true
|
||||
if (this !is FirFunctionCall) return false
|
||||
val name = (calleeReference as? FirResolvedNamedReference)?.name
|
||||
val name = (calleeReference as? FirResolvedNamedReference)?.name ?: getFallbackCompoundCalleeName()
|
||||
return name == OperatorNameConventions.SET || name in OperatorNameConventions.ASSIGNMENT_OPERATIONS
|
||||
}
|
||||
|
||||
/**
|
||||
* If the callee reference is not a [FirResolvedNamedReference], we can get the compound callee name from the source instead. For
|
||||
* example, if the callee reference is a [FirErrorNamedReference] with an unresolved name `plusAssign`, the operation element type from
|
||||
* the source will be `KtTokens.PLUSEQ`, which can be transformed to `plusAssign`.
|
||||
*/
|
||||
private fun FirElement.getFallbackCompoundCalleeName(): Name? {
|
||||
val psi = source.psi as? KtOperationExpression ?: return null
|
||||
val operationReference = psi.operationReference
|
||||
return operationReference.getAssignmentOperationName() ?: operationReference.getReferencedNameAsName()
|
||||
}
|
||||
|
||||
private fun KtSimpleNameExpression.getAssignmentOperationName(): Name? {
|
||||
val firOperation = getReferencedNameElementType().toFirOperationOrNull() ?: return null
|
||||
return FirOperationNameConventions.ASSIGNMENTS[firOperation]
|
||||
}
|
||||
|
||||
private val FirConstExpression<*>.isConverted: Boolean
|
||||
get() {
|
||||
val firSourcePsi = this.source?.psi ?: return false
|
||||
|
||||
+12
-3
@@ -34,8 +34,14 @@ import org.jetbrains.kotlin.fir.references.builder.buildDelegateFieldReference
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildImplicitThisReference
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.ConeStarProjection
|
||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.impl.*
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
@@ -141,6 +147,9 @@ fun IElementType.toUnaryName(): Name? {
|
||||
}
|
||||
|
||||
fun IElementType.toFirOperation(): FirOperation =
|
||||
toFirOperationOrNull() ?: error("Cannot convert element type to FIR operation: $this")
|
||||
|
||||
fun IElementType.toFirOperationOrNull(): FirOperation? =
|
||||
when (this) {
|
||||
KtTokens.LT -> FirOperation.LT
|
||||
KtTokens.GT -> FirOperation.GT
|
||||
@@ -161,7 +170,7 @@ fun IElementType.toFirOperation(): FirOperation =
|
||||
KtTokens.AS_KEYWORD -> FirOperation.AS
|
||||
KtTokens.AS_SAFE -> FirOperation.SAFE_AS
|
||||
|
||||
else -> throw AssertionError(this.toString())
|
||||
else -> null
|
||||
}
|
||||
|
||||
fun FirExpression.generateNotNullOrOther(
|
||||
|
||||
Reference in New Issue
Block a user