[FIR] Replace all necessary usages of operator call with new ones
#KT-38333 Fixed
This commit is contained in:
@@ -869,6 +869,10 @@ class Fir2IrVisitor(
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: Any?): IrElement {
|
||||
return operatorGenerator.convertEqualityOperatorCall(equalityOperatorCall)
|
||||
}
|
||||
|
||||
override fun visitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, data: Any?): IrElement {
|
||||
return checkNotNullCall.convertWithOffsets { startOffset, endOffset ->
|
||||
IrCallImpl(
|
||||
|
||||
+14
-8
@@ -35,8 +35,15 @@ internal class OperatorExpressionGenerator(
|
||||
}
|
||||
|
||||
fun convertOperatorCall(operatorCall: FirOperatorCall): IrExpression {
|
||||
return operatorCall.convertWithOffsets { startOffset, endOffset ->
|
||||
generateOperatorCall(startOffset, endOffset, operatorCall.operation, operatorCall.arguments)
|
||||
return when (val operation = operatorCall.operation) {
|
||||
FirOperation.EXCL -> visitor.convertToIrExpression(operatorCall.arguments[0]).negate(IrStatementOrigin.EXCL)
|
||||
else -> error("Unexpected operation: $operation")
|
||||
}
|
||||
}
|
||||
|
||||
fun convertEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall): IrExpression {
|
||||
return equalityOperatorCall.convertWithOffsets { startOffset, endOffset ->
|
||||
generateEqualityOperatorCall(startOffset, endOffset, equalityOperatorCall.operation, equalityOperatorCall.arguments)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,16 +91,15 @@ internal class OperatorExpressionGenerator(
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateOperatorCall(
|
||||
private fun generateEqualityOperatorCall(
|
||||
startOffset: Int, endOffset: Int, operation: FirOperation, arguments: List<FirExpression>
|
||||
): IrExpression = when (operation) {
|
||||
FirOperation.EQ, FirOperation.NOT_EQ -> generateEqualityOperatorCall(startOffset, endOffset, operation, arguments)
|
||||
FirOperation.IDENTITY, FirOperation.NOT_IDENTITY -> generateIdentityOperatorCall(startOffset, endOffset, operation, arguments)
|
||||
FirOperation.EXCL -> visitor.convertToIrExpression(arguments[0]).negate(IrStatementOrigin.EXCL)
|
||||
FirOperation.EQ, FirOperation.NOT_EQ -> transformEqualityOperatorCall(startOffset, endOffset, operation, arguments)
|
||||
FirOperation.IDENTITY, FirOperation.NOT_IDENTITY -> transformIdentityOperatorCall(startOffset, endOffset, operation, arguments)
|
||||
else -> error("Unexpected operation: $operation")
|
||||
}
|
||||
|
||||
private fun generateEqualityOperatorCall(
|
||||
private fun transformEqualityOperatorCall(
|
||||
startOffset: Int, endOffset: Int, operation: FirOperation, arguments: List<FirExpression>
|
||||
): IrExpression {
|
||||
val origin = when (operation) {
|
||||
@@ -117,7 +123,7 @@ internal class OperatorExpressionGenerator(
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateIdentityOperatorCall(
|
||||
private fun transformIdentityOperatorCall(
|
||||
startOffset: Int, endOffset: Int, operation: FirOperation, arguments: List<FirExpression>
|
||||
): IrExpression {
|
||||
val origin = when (operation) {
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ private object ConeConditionalEffectToFirVisitor : ConeContractDescriptionVisito
|
||||
|
||||
override fun visitIsNullPredicate(isNullPredicate: ConeIsNullPredicate, data: Map<Int, FirExpression>): FirExpression? {
|
||||
val argument = isNullPredicate.arg.accept(this, data) ?: return null
|
||||
return buildOperatorCall {
|
||||
return buildEqualityOperatorCall {
|
||||
operation = if (isNullPredicate.isNegated) {
|
||||
FirOperation.NOT_EQ
|
||||
} else {
|
||||
|
||||
+9
-10
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
|
||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
@@ -88,9 +87,9 @@ class FirWhenExhaustivenessTransformer(private val bodyResolveComponents: BodyRe
|
||||
private object EnumExhaustivenessVisitor : FirVisitor<Unit, EnumExhaustivenessData>() {
|
||||
override fun visitElement(element: FirElement, data: EnumExhaustivenessData) {}
|
||||
|
||||
override fun visitOperatorCall(operatorCall: FirOperatorCall, data: EnumExhaustivenessData) {
|
||||
if (operatorCall.operation == FirOperation.EQ) {
|
||||
when (val argument = operatorCall.arguments[1]) {
|
||||
override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: EnumExhaustivenessData) {
|
||||
if (equalityOperatorCall.operation.let { it == FirOperation.EQ || it == FirOperation.IDENTITY }) {
|
||||
when (val argument = equalityOperatorCall.arguments[1]) {
|
||||
is FirConstExpression<*> -> {
|
||||
if (argument.value == null) {
|
||||
data.containsNull = true
|
||||
@@ -173,9 +172,9 @@ class FirWhenExhaustivenessTransformer(private val bodyResolveComponents: BodyRe
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitOperatorCall(operatorCall: FirOperatorCall, data: SealedExhaustivenessData) {
|
||||
if (operatorCall.operation == FirOperation.EQ) {
|
||||
when (val argument = operatorCall.arguments[1]) {
|
||||
override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: SealedExhaustivenessData) {
|
||||
if (equalityOperatorCall.operation.let { it == FirOperation.EQ || it == FirOperation.IDENTITY }) {
|
||||
when (val argument = equalityOperatorCall.arguments[1]) {
|
||||
is FirConstExpression<*> -> {
|
||||
if (argument.value == null) {
|
||||
data.containsNull = true
|
||||
@@ -220,9 +219,9 @@ class FirWhenExhaustivenessTransformer(private val bodyResolveComponents: BodyRe
|
||||
private object BooleanExhaustivenessVisitor : FirVisitor<Unit, BooleanExhaustivenessFlags>() {
|
||||
override fun visitElement(element: FirElement, data: BooleanExhaustivenessFlags) {}
|
||||
|
||||
override fun visitOperatorCall(operatorCall: FirOperatorCall, data: BooleanExhaustivenessFlags) {
|
||||
if (operatorCall.operation == FirOperation.EQ) {
|
||||
val argument = operatorCall.arguments[1]
|
||||
override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: BooleanExhaustivenessFlags) {
|
||||
if (equalityOperatorCall.operation.let { it == FirOperation.EQ || it == FirOperation.IDENTITY }) {
|
||||
val argument = equalityOperatorCall.arguments[1]
|
||||
if (argument is FirConstExpression<*>) {
|
||||
when (argument.value) {
|
||||
true -> data.containsTrue = true
|
||||
|
||||
+22
-16
@@ -120,22 +120,6 @@ class IntegerLiteralTypeApproximationTransformer(
|
||||
}
|
||||
|
||||
override fun transformOperatorCall(operatorCall: FirOperatorCall, data: ConeKotlinType?): CompositeTransformResult<FirStatement> {
|
||||
if (operatorCall.operation !in FirOperation.BOOLEANS) return operatorCall.compose()
|
||||
val leftArgument = operatorCall.arguments[0]
|
||||
val rightArgument = operatorCall.arguments[1]
|
||||
|
||||
val leftIsIlt = leftArgument.typeRef.coneTypeSafe<ConeIntegerLiteralType>() != null
|
||||
val rightIsIlt = rightArgument.typeRef.coneTypeSafe<ConeIntegerLiteralType>() != null
|
||||
|
||||
val expectedType: ConeKotlinType? = when {
|
||||
!leftIsIlt && !rightIsIlt -> return operatorCall.compose()
|
||||
leftIsIlt && rightIsIlt -> null
|
||||
leftIsIlt -> rightArgument.typeRef.coneType
|
||||
rightIsIlt -> leftArgument.typeRef.coneType
|
||||
else -> throw IllegalStateException()
|
||||
}
|
||||
|
||||
operatorCall.argumentList.transformArguments(this, expectedType)
|
||||
return operatorCall.compose()
|
||||
}
|
||||
|
||||
@@ -148,6 +132,28 @@ class IntegerLiteralTypeApproximationTransformer(
|
||||
return typeOperatorCall.compose()
|
||||
}
|
||||
|
||||
override fun transformEqualityOperatorCall(
|
||||
equalityOperatorCall: FirEqualityOperatorCall,
|
||||
data: ConeKotlinType?
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
val leftArgument = equalityOperatorCall.arguments[0]
|
||||
val rightArgument = equalityOperatorCall.arguments[1]
|
||||
|
||||
val leftIsIlt = leftArgument.typeRef.coneTypeSafe<ConeIntegerLiteralType>() != null
|
||||
val rightIsIlt = rightArgument.typeRef.coneTypeSafe<ConeIntegerLiteralType>() != null
|
||||
|
||||
val expectedType: ConeKotlinType? = when {
|
||||
!leftIsIlt && !rightIsIlt -> return equalityOperatorCall.compose()
|
||||
leftIsIlt && rightIsIlt -> null
|
||||
leftIsIlt -> rightArgument.typeRef.coneType
|
||||
rightIsIlt -> leftArgument.typeRef.coneType
|
||||
else -> throw IllegalStateException()
|
||||
}
|
||||
|
||||
equalityOperatorCall.argumentList.transformArguments(this, expectedType)
|
||||
return equalityOperatorCall.compose()
|
||||
}
|
||||
|
||||
override fun transformCheckedSafeCallSubject(
|
||||
checkedSafeCallSubject: FirCheckedSafeCallSubject,
|
||||
data: ConeKotlinType?
|
||||
|
||||
+14
@@ -140,6 +140,20 @@ open class FirBodyResolveTransformer(
|
||||
return expressionsTransformer.transformTypeOperatorCall(typeOperatorCall, data)
|
||||
}
|
||||
|
||||
override fun transformAssignmentOperatorStatement(
|
||||
assignmentOperatorStatement: FirAssignmentOperatorStatement,
|
||||
data: ResolutionMode
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
return expressionsTransformer.transformAssignmentOperatorStatement(assignmentOperatorStatement, data)
|
||||
}
|
||||
|
||||
override fun transformEqualityOperatorCall(
|
||||
equalityOperatorCall: FirEqualityOperatorCall,
|
||||
data: ResolutionMode
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
return expressionsTransformer.transformEqualityOperatorCall(equalityOperatorCall, data)
|
||||
}
|
||||
|
||||
override fun transformCheckNotNullCall(
|
||||
checkNotNullCall: FirCheckNotNullCall,
|
||||
data: ResolutionMode
|
||||
|
||||
+85
-82
@@ -334,99 +334,102 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
||||
}.transformSingle(integerLiteralTypeApproximator, null).also(dataFlowAnalyzer::exitComparisonExpressionCall).compose()
|
||||
}
|
||||
|
||||
override fun transformOperatorCall(operatorCall: FirOperatorCall, data: ResolutionMode): CompositeTransformResult<FirStatement> {
|
||||
if (operatorCall.operation in FirOperation.BOOLEANS) {
|
||||
// TODO: add approximation of integer literals
|
||||
val result = (operatorCall.transformChildren(transformer, ResolutionMode.ContextIndependent) as FirOperatorCall).also {
|
||||
it.resultType = operatorCall.typeRef.resolvedTypeFromPrototype(builtinTypes.booleanType.type)
|
||||
}.transformSingle(integerLiteralTypeApproximator, null)
|
||||
dataFlowAnalyzer.exitOperatorCall(result)
|
||||
return result.compose()
|
||||
override fun transformAssignmentOperatorStatement(
|
||||
assignmentOperatorStatement: FirAssignmentOperatorStatement,
|
||||
data: ResolutionMode
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
require(assignmentOperatorStatement.operation != FirOperation.ASSIGN)
|
||||
|
||||
assignmentOperatorStatement.annotations.forEach { it.accept(this, data) }
|
||||
val leftArgument = assignmentOperatorStatement.leftArgument.transformSingle(transformer, ResolutionMode.ContextIndependent)
|
||||
val rightArgument = assignmentOperatorStatement.rightArgument.transformSingle(transformer, ResolutionMode.ContextDependent)
|
||||
|
||||
fun createFunctionCall(name: Name) = buildFunctionCall {
|
||||
source = assignmentOperatorStatement.source?.fakeElement(FirFakeSourceElementKind.DesugaredCompoundAssignment)
|
||||
explicitReceiver = leftArgument
|
||||
argumentList = buildUnaryArgumentList(rightArgument)
|
||||
calleeReference = buildSimpleNamedReference {
|
||||
source = assignmentOperatorStatement.source
|
||||
this.name = name
|
||||
candidateSymbol = null
|
||||
}
|
||||
}
|
||||
|
||||
if (operatorCall.operation in FirOperation.ASSIGNMENTS) {
|
||||
require(operatorCall.operation != FirOperation.ASSIGN)
|
||||
// x.plusAssign(y)
|
||||
val assignmentOperatorName = FirOperationNameConventions.ASSIGNMENTS.getValue(assignmentOperatorStatement.operation)
|
||||
val assignOperatorCall = createFunctionCall(assignmentOperatorName)
|
||||
val resolvedAssignCall = resolveCandidateForAssignmentOperatorCall {
|
||||
assignOperatorCall.transformSingle(this, ResolutionMode.ContextDependent)
|
||||
}
|
||||
val assignCallReference = resolvedAssignCall.calleeReference as? FirNamedReferenceWithCandidate
|
||||
val assignIsError = assignCallReference?.isError ?: true
|
||||
// x = x + y
|
||||
val simpleOperatorName = FirOperationNameConventions.ASSIGNMENTS_TO_SIMPLE_OPERATOR.getValue(assignmentOperatorStatement.operation)
|
||||
val simpleOperatorCall = createFunctionCall(simpleOperatorName)
|
||||
val resolvedOperatorCall = resolveCandidateForAssignmentOperatorCall {
|
||||
simpleOperatorCall.transformSingle(this, ResolutionMode.ContextDependent)
|
||||
}
|
||||
val operatorCallReference = resolvedOperatorCall.calleeReference as? FirNamedReferenceWithCandidate
|
||||
val operatorIsError = operatorCallReference?.isError ?: true
|
||||
|
||||
operatorCall.annotations.forEach { it.accept(this, data) }
|
||||
var (leftArgument, rightArgument) = operatorCall.arguments
|
||||
@Suppress("NAME_SHADOWING")
|
||||
leftArgument = leftArgument.transformSingle(transformer, ResolutionMode.ContextIndependent)
|
||||
rightArgument = rightArgument.transformSingle(transformer, ResolutionMode.ContextDependent)
|
||||
|
||||
fun createFunctionCall(name: Name) = buildFunctionCall {
|
||||
source = operatorCall.source?.fakeElement(FirFakeSourceElementKind.DesugaredCompoundAssignment)
|
||||
explicitReceiver = leftArgument
|
||||
argumentList = buildUnaryArgumentList(rightArgument)
|
||||
calleeReference = buildSimpleNamedReference {
|
||||
source = operatorCall.source
|
||||
this.name = name
|
||||
candidateSymbol = null
|
||||
}
|
||||
val lhsReference = leftArgument.toResolvedCallableReference()
|
||||
val lhsVariable = (lhsReference?.resolvedSymbol as? FirVariableSymbol<*>)?.fir
|
||||
val lhsIsVar = lhsVariable?.isVar == true
|
||||
return when {
|
||||
operatorIsError || (!lhsIsVar && !assignIsError) -> {
|
||||
callCompleter.completeCall(resolvedAssignCall, noExpectedType)
|
||||
dataFlowAnalyzer.exitFunctionCall(resolvedAssignCall, callCompleted = true)
|
||||
resolvedAssignCall.compose()
|
||||
}
|
||||
|
||||
// x.plusAssign(y)
|
||||
val assignmentOperatorName = FirOperationNameConventions.ASSIGNMENTS.getValue(operatorCall.operation)
|
||||
val assignOperatorCall = createFunctionCall(assignmentOperatorName)
|
||||
val resolvedAssignCall = resolveCandidateForAssignmentOperatorCall {
|
||||
assignOperatorCall.transformSingle(this, ResolutionMode.ContextDependent)
|
||||
}
|
||||
val assignCallReference = resolvedAssignCall.calleeReference as? FirNamedReferenceWithCandidate
|
||||
val assignIsError = assignCallReference?.isError ?: true
|
||||
// x = x + y
|
||||
val simpleOperatorName = FirOperationNameConventions.ASSIGNMENTS_TO_SIMPLE_OPERATOR.getValue(operatorCall.operation)
|
||||
val simpleOperatorCall = createFunctionCall(simpleOperatorName)
|
||||
val resolvedOperatorCall = resolveCandidateForAssignmentOperatorCall {
|
||||
simpleOperatorCall.transformSingle(this, ResolutionMode.ContextDependent)
|
||||
}
|
||||
val operatorCallReference = resolvedOperatorCall.calleeReference as? FirNamedReferenceWithCandidate
|
||||
val operatorIsError = operatorCallReference?.isError ?: true
|
||||
|
||||
val lhsReference = leftArgument.toResolvedCallableReference()
|
||||
val lhsVariable = (lhsReference?.resolvedSymbol as? FirVariableSymbol<*>)?.fir
|
||||
val lhsIsVar = lhsVariable?.isVar == true
|
||||
return when {
|
||||
operatorIsError || (!lhsIsVar && !assignIsError) -> {
|
||||
callCompleter.completeCall(resolvedAssignCall, noExpectedType)
|
||||
dataFlowAnalyzer.exitFunctionCall(resolvedAssignCall, callCompleted = true)
|
||||
resolvedAssignCall.compose()
|
||||
}
|
||||
assignIsError -> {
|
||||
callCompleter.completeCall(resolvedOperatorCall, lhsVariable?.returnTypeRef ?: noExpectedType)
|
||||
dataFlowAnalyzer.exitFunctionCall(resolvedOperatorCall, callCompleted = true)
|
||||
val assignment =
|
||||
buildVariableAssignment {
|
||||
source = operatorCall.source
|
||||
rValue = resolvedOperatorCall
|
||||
calleeReference = if (lhsIsVar)
|
||||
lhsReference!!
|
||||
else
|
||||
buildErrorNamedReference {
|
||||
source = operatorCall.argument.source
|
||||
diagnostic = ConeVariableExpectedError()
|
||||
}
|
||||
(leftArgument as? FirQualifiedAccess)?.let {
|
||||
dispatchReceiver = it.dispatchReceiver
|
||||
extensionReceiver = it.extensionReceiver
|
||||
assignIsError -> {
|
||||
callCompleter.completeCall(resolvedOperatorCall, lhsVariable?.returnTypeRef ?: noExpectedType)
|
||||
dataFlowAnalyzer.exitFunctionCall(resolvedOperatorCall, callCompleted = true)
|
||||
val assignment =
|
||||
buildVariableAssignment {
|
||||
source = assignmentOperatorStatement.source
|
||||
rValue = resolvedOperatorCall
|
||||
calleeReference = when {
|
||||
lhsIsVar -> lhsReference!!
|
||||
else -> buildErrorNamedReference {
|
||||
source = assignmentOperatorStatement.leftArgument.source
|
||||
diagnostic = ConeVariableExpectedError()
|
||||
}
|
||||
}
|
||||
assignment.transform(transformer, ResolutionMode.ContextIndependent)
|
||||
}
|
||||
else -> {
|
||||
val operatorCallSymbol = operatorCallReference?.candidateSymbol
|
||||
val assignmentCallSymbol = assignCallReference?.candidateSymbol
|
||||
(leftArgument as? FirQualifiedAccess)?.let {
|
||||
dispatchReceiver = it.dispatchReceiver
|
||||
extensionReceiver = it.extensionReceiver
|
||||
}
|
||||
}
|
||||
assignment.transform(transformer, ResolutionMode.ContextIndependent)
|
||||
}
|
||||
else -> {
|
||||
val operatorCallSymbol = operatorCallReference?.candidateSymbol
|
||||
val assignmentCallSymbol = assignCallReference?.candidateSymbol
|
||||
|
||||
requireNotNull(operatorCallSymbol)
|
||||
requireNotNull(assignmentCallSymbol)
|
||||
requireNotNull(operatorCallSymbol)
|
||||
requireNotNull(assignmentCallSymbol)
|
||||
|
||||
buildErrorExpression {
|
||||
source = operatorCall.source
|
||||
diagnostic =
|
||||
ConeOperatorAmbiguityError(listOf(operatorCallSymbol, assignmentCallSymbol))
|
||||
}.compose()
|
||||
}
|
||||
buildErrorExpression {
|
||||
source = assignmentOperatorStatement.source
|
||||
diagnostic = ConeOperatorAmbiguityError(listOf(operatorCallSymbol, assignmentCallSymbol))
|
||||
}.compose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun transformEqualityOperatorCall(
|
||||
equalityOperatorCall: FirEqualityOperatorCall,
|
||||
data: ResolutionMode
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
// TODO: add approximation of integer literals
|
||||
val result = (equalityOperatorCall.transformChildren(transformer, ResolutionMode.ContextIndependent) as FirEqualityOperatorCall)
|
||||
.also { it.resultType = equalityOperatorCall.typeRef.resolvedTypeFromPrototype(builtinTypes.booleanType.type) }
|
||||
.transformSingle(integerLiteralTypeApproximator, null)
|
||||
dataFlowAnalyzer.exitEqualityOperatorCall(result)
|
||||
return result.compose()
|
||||
}
|
||||
|
||||
override fun transformOperatorCall(operatorCall: FirOperatorCall, data: ResolutionMode): CompositeTransformResult<FirStatement> {
|
||||
throw IllegalArgumentException(operatorCall.render())
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -96,15 +96,15 @@ class ConeEffectExtractor(
|
||||
return ConeBinaryLogicExpression(left, right, binaryLogicExpression.kind)
|
||||
}
|
||||
|
||||
override fun visitOperatorCall(operatorCall: FirOperatorCall, data: Nothing?): ConeContractDescriptionElement? {
|
||||
val isNegated = when (operatorCall.operation) {
|
||||
override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: Nothing?): ConeContractDescriptionElement? {
|
||||
val isNegated = when (equalityOperatorCall.operation) {
|
||||
FirOperation.EQ -> false
|
||||
FirOperation.NOT_EQ -> true
|
||||
else -> return null
|
||||
}
|
||||
val const = operatorCall.arguments[1] as? FirConstExpression<*> ?: return null
|
||||
val const = equalityOperatorCall.arguments[1] as? FirConstExpression<*> ?: return null
|
||||
if (const.kind != FirConstKind.Null) return null
|
||||
val arg = operatorCall.arguments[0].accept(this, null) as? ConeValueParameterReference ?: return null
|
||||
val arg = equalityOperatorCall.arguments[0].accept(this, null) as? ConeValueParameterReference ?: return null
|
||||
return ConeIsNullPredicate(arg, isNegated)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user