Rename InvocationKind to EventOccurrencesRange
This commit is contained in:
+9
-9
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.cfa
|
||||
|
||||
import kotlinx.collections.immutable.PersistentMap
|
||||
import kotlinx.collections.immutable.persistentMapOf
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.contracts.description.isDefinitelyVisited
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
@@ -37,7 +37,7 @@ class FirPropertyInitializationAnalyzer {
|
||||
val reference = node.fir.calleeReference as? FirResolvedNamedReference ?: return
|
||||
val symbol = reference.resolvedSymbol as? FirPropertySymbol ?: return
|
||||
if (symbol !in localProperties) return
|
||||
val kind = data.getValue(node)[symbol] ?: InvocationKind.ZERO
|
||||
val kind = data.getValue(node)[symbol] ?: EventOccurrencesRange.ZERO
|
||||
if (!kind.isDefinitelyVisited()) {
|
||||
node.fir.source?.let {
|
||||
reporter.report(FirErrors.UNINITIALIZED_VARIABLE.on(it, symbol))
|
||||
@@ -47,20 +47,20 @@ class FirPropertyInitializationAnalyzer {
|
||||
}
|
||||
|
||||
private class PropertyInitializationInfo(
|
||||
map: PersistentMap<FirPropertySymbol, InvocationKind> = persistentMapOf()
|
||||
) : ControlFlowInfo<PropertyInitializationInfo, FirPropertySymbol, InvocationKind>(map) {
|
||||
map: PersistentMap<FirPropertySymbol, EventOccurrencesRange> = persistentMapOf()
|
||||
) : ControlFlowInfo<PropertyInitializationInfo, FirPropertySymbol, EventOccurrencesRange>(map) {
|
||||
companion object {
|
||||
val EMPTY = PropertyInitializationInfo()
|
||||
}
|
||||
|
||||
override val constructor: (PersistentMap<FirPropertySymbol, InvocationKind>) -> PropertyInitializationInfo =
|
||||
override val constructor: (PersistentMap<FirPropertySymbol, EventOccurrencesRange>) -> PropertyInitializationInfo =
|
||||
::PropertyInitializationInfo
|
||||
|
||||
fun merge(other: PropertyInitializationInfo): PropertyInitializationInfo {
|
||||
var result = this
|
||||
for (symbol in keys.union(other.keys)) {
|
||||
val kind1 = this[symbol] ?: InvocationKind.ZERO
|
||||
val kind2 = other[symbol] ?: InvocationKind.ZERO
|
||||
val kind1 = this[symbol] ?: EventOccurrencesRange.ZERO
|
||||
val kind2 = other[symbol] ?: EventOccurrencesRange.ZERO
|
||||
result = result.put(symbol, kind1 or kind2)
|
||||
}
|
||||
return result
|
||||
@@ -121,8 +121,8 @@ class FirPropertyInitializationAnalyzer {
|
||||
dataForNode: PropertyInitializationInfo,
|
||||
symbol: FirPropertySymbol
|
||||
): PropertyInitializationInfo {
|
||||
val existingKind = dataForNode[symbol] ?: InvocationKind.ZERO
|
||||
val kind = existingKind and InvocationKind.EXACTLY_ONCE
|
||||
val existingKind = dataForNode[symbol] ?: EventOccurrencesRange.ZERO
|
||||
val kind = existingKind + EventOccurrencesRange.EXACTLY_ONCE
|
||||
return dataForNode.put(symbol, kind)
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -193,10 +193,10 @@ class FirContractSerializer {
|
||||
}
|
||||
}
|
||||
|
||||
private fun invocationKindProtobufEnum(kind: InvocationKind): ProtoBuf.Effect.InvocationKind? = when (kind) {
|
||||
InvocationKind.AT_MOST_ONCE -> ProtoBuf.Effect.InvocationKind.AT_MOST_ONCE
|
||||
InvocationKind.EXACTLY_ONCE -> ProtoBuf.Effect.InvocationKind.EXACTLY_ONCE
|
||||
InvocationKind.AT_LEAST_ONCE -> ProtoBuf.Effect.InvocationKind.AT_LEAST_ONCE
|
||||
private fun invocationKindProtobufEnum(kind: EventOccurrencesRange): ProtoBuf.Effect.InvocationKind? = when (kind) {
|
||||
EventOccurrencesRange.AT_MOST_ONCE -> ProtoBuf.Effect.InvocationKind.AT_MOST_ONCE
|
||||
EventOccurrencesRange.EXACTLY_ONCE -> ProtoBuf.Effect.InvocationKind.EXACTLY_ONCE
|
||||
EventOccurrencesRange.AT_LEAST_ONCE -> ProtoBuf.Effect.InvocationKind.AT_LEAST_ONCE
|
||||
else -> null
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir
|
||||
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
|
||||
@@ -69,7 +69,7 @@ fun FirAnonymousFunction.copy(
|
||||
typeRef: FirTypeRef = this.typeRef,
|
||||
label: FirLabel? = this.label,
|
||||
controlFlowGraphReference: FirControlFlowGraphReference = this.controlFlowGraphReference,
|
||||
invocationKind: InvocationKind? = this.invocationKind
|
||||
eventOccurrencesRange: EventOccurrencesRange? = this.eventOccurrencesRange
|
||||
): FirAnonymousFunction {
|
||||
return buildAnonymousFunction {
|
||||
this.source = source
|
||||
@@ -85,7 +85,7 @@ fun FirAnonymousFunction.copy(
|
||||
this.typeRef = typeRef
|
||||
this.label = label
|
||||
this.controlFlowGraphReference = controlFlowGraphReference
|
||||
this.invocationKind = invocationKind
|
||||
this.eventOccurrencesRange = eventOccurrencesRange
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.deserialization
|
||||
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
|
||||
import org.jetbrains.kotlin.fir.contracts.builder.buildResolvedContractDescription
|
||||
import org.jetbrains.kotlin.fir.contracts.description.*
|
||||
@@ -60,7 +60,7 @@ class FirContractDeserializer(private val c: FirDeserializationContext) {
|
||||
val invocationKind = if (proto.hasKind())
|
||||
proto.kind.toDescriptorInvocationKind() ?: return null
|
||||
else
|
||||
InvocationKind.UNKNOWN
|
||||
EventOccurrencesRange.UNKNOWN
|
||||
ConeCallsEffectDeclaration(callable, invocationKind)
|
||||
}
|
||||
}
|
||||
@@ -141,10 +141,10 @@ class FirContractDeserializer(private val c: FirDeserializationContext) {
|
||||
ConeBooleanValueParameterReference(valueParameterIndex, name)
|
||||
}
|
||||
|
||||
private fun ProtoBuf.Effect.InvocationKind.toDescriptorInvocationKind(): InvocationKind? = when (this) {
|
||||
ProtoBuf.Effect.InvocationKind.AT_MOST_ONCE -> InvocationKind.AT_MOST_ONCE
|
||||
ProtoBuf.Effect.InvocationKind.EXACTLY_ONCE -> InvocationKind.EXACTLY_ONCE
|
||||
ProtoBuf.Effect.InvocationKind.AT_LEAST_ONCE -> InvocationKind.AT_LEAST_ONCE
|
||||
private fun ProtoBuf.Effect.InvocationKind.toDescriptorInvocationKind(): EventOccurrencesRange? = when (this) {
|
||||
ProtoBuf.Effect.InvocationKind.AT_MOST_ONCE -> EventOccurrencesRange.AT_MOST_ONCE
|
||||
ProtoBuf.Effect.InvocationKind.EXACTLY_ONCE -> EventOccurrencesRange.EXACTLY_ONCE
|
||||
ProtoBuf.Effect.InvocationKind.AT_LEAST_ONCE -> EventOccurrencesRange.AT_LEAST_ONCE
|
||||
}
|
||||
|
||||
private fun extractType(proto: ProtoBuf.Expression): ConeKotlinType? {
|
||||
|
||||
+8
-8
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.dfa.cfg
|
||||
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSymbolOwner
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
@@ -207,7 +207,7 @@ class ControlFlowGraphBuilder {
|
||||
}
|
||||
|
||||
fun enterAnonymousFunction(anonymousFunction: FirAnonymousFunction): Pair<PostponedLambdaEnterNode?, FunctionEnterNode> {
|
||||
val invocationKind = anonymousFunction.invocationKind
|
||||
val invocationKind = anonymousFunction.eventOccurrencesRange
|
||||
|
||||
var previousNodeIsNew = false
|
||||
val symbol = anonymousFunction.symbol
|
||||
@@ -256,15 +256,15 @@ class ControlFlowGraphBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
private val InvocationKind?.hasTowardEdge: Boolean
|
||||
private val EventOccurrencesRange?.hasTowardEdge: Boolean
|
||||
get() = when (this) {
|
||||
InvocationKind.AT_MOST_ONCE, InvocationKind.UNKNOWN -> true
|
||||
EventOccurrencesRange.AT_MOST_ONCE, EventOccurrencesRange.UNKNOWN -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
private val InvocationKind?.hasBackEdge: Boolean
|
||||
private val EventOccurrencesRange?.hasBackEdge: Boolean
|
||||
get() = when (this) {
|
||||
InvocationKind.AT_LEAST_ONCE, InvocationKind.UNKNOWN -> true
|
||||
EventOccurrencesRange.AT_LEAST_ONCE, EventOccurrencesRange.UNKNOWN -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
@@ -293,7 +293,7 @@ class ControlFlowGraphBuilder {
|
||||
lastNodes.push(postponedExitNode)
|
||||
}
|
||||
|
||||
val invocationKind = anonymousFunction.invocationKind
|
||||
val invocationKind = anonymousFunction.eventOccurrencesRange
|
||||
if (invocationKind != null) {
|
||||
addEdge(exitNode, postponedExitNode, preferredKind = EdgeKind.CfgForward)
|
||||
} else {
|
||||
@@ -301,7 +301,7 @@ class ControlFlowGraphBuilder {
|
||||
CFGNode.addJustKindEdge(postponedEnterNode, postponedExitNode, kind, propagateDeadness = true)
|
||||
}
|
||||
|
||||
if (invocationKind == InvocationKind.EXACTLY_ONCE && shouldPassFlowFromInplaceLambda.top()) {
|
||||
if (invocationKind == EventOccurrencesRange.EXACTLY_ONCE && shouldPassFlowFromInplaceLambda.top()) {
|
||||
exitsFromCompletedPostponedAnonymousFunctions += postponedExitNode
|
||||
}
|
||||
|
||||
|
||||
+8
-8
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.transformers
|
||||
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.contracts.description.ConeCallsEffectDeclaration
|
||||
import org.jetbrains.kotlin.fir.contracts.effects
|
||||
@@ -19,14 +19,14 @@ import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
import org.jetbrains.kotlin.fir.visitors.compose
|
||||
|
||||
object InvocationKindTransformer : FirTransformer<Nothing?>() {
|
||||
private object ArgumentsTransformer : FirTransformer<Pair<Map<FirExpression, InvocationKind>, InvocationKind?>>() {
|
||||
override fun <E : FirElement> transformElement(element: E, data: Pair<Map<FirExpression, InvocationKind>, InvocationKind?>): CompositeTransformResult<E> {
|
||||
private object ArgumentsTransformer : FirTransformer<Pair<Map<FirExpression, EventOccurrencesRange>, EventOccurrencesRange?>>() {
|
||||
override fun <E : FirElement> transformElement(element: E, data: Pair<Map<FirExpression, EventOccurrencesRange>, EventOccurrencesRange?>): CompositeTransformResult<E> {
|
||||
return element.compose()
|
||||
}
|
||||
|
||||
override fun transformAnonymousFunction(
|
||||
anonymousFunction: FirAnonymousFunction,
|
||||
data: Pair<Map<FirExpression, InvocationKind>, InvocationKind?>
|
||||
data: Pair<Map<FirExpression, EventOccurrencesRange>, EventOccurrencesRange?>
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
val kind = data.second ?: data.first[anonymousFunction]
|
||||
if (kind != null) {
|
||||
@@ -37,7 +37,7 @@ object InvocationKindTransformer : FirTransformer<Nothing?>() {
|
||||
|
||||
override fun transformLambdaArgumentExpression(
|
||||
lambdaArgumentExpression: FirLambdaArgumentExpression,
|
||||
data: Pair<Map<FirExpression, InvocationKind>, InvocationKind?>
|
||||
data: Pair<Map<FirExpression, EventOccurrencesRange>, EventOccurrencesRange?>
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
return data.first[lambdaArgumentExpression]?.let {
|
||||
(lambdaArgumentExpression.transformChildren(this, data.first to it) as FirStatement).compose()
|
||||
@@ -46,7 +46,7 @@ object InvocationKindTransformer : FirTransformer<Nothing?>() {
|
||||
|
||||
override fun transformNamedArgumentExpression(
|
||||
namedArgumentExpression: FirNamedArgumentExpression,
|
||||
data: Pair<Map<FirExpression, InvocationKind>, InvocationKind?>
|
||||
data: Pair<Map<FirExpression, EventOccurrencesRange>, EventOccurrencesRange?>
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
return data.first[namedArgumentExpression]?.let {
|
||||
(namedArgumentExpression.transformChildren(this, data.first to it) as FirStatement).compose()
|
||||
@@ -74,7 +74,7 @@ object InvocationKindTransformer : FirTransformer<Nothing?>() {
|
||||
parameter to argument
|
||||
}.toMap()
|
||||
|
||||
val invocationKindMapping = mutableMapOf<FirExpression, InvocationKind>()
|
||||
val invocationKindMapping = mutableMapOf<FirExpression, EventOccurrencesRange>()
|
||||
for (effect in callsEffects) {
|
||||
// TODO: Support callsInPlace contracts on receivers
|
||||
val valueParameter = function.valueParameters.getOrNull(effect.valueParameterReference.parameterIndex) ?: continue
|
||||
@@ -83,7 +83,7 @@ object InvocationKindTransformer : FirTransformer<Nothing?>() {
|
||||
}
|
||||
if (isInline) {
|
||||
for (argument in functionCall.arguments) {
|
||||
invocationKindMapping.putIfAbsent(argument, InvocationKind.UNKNOWN)
|
||||
invocationKindMapping.putIfAbsent(argument, EventOccurrencesRange.UNKNOWN)
|
||||
}
|
||||
}
|
||||
if (invocationKindMapping.isEmpty()) {
|
||||
|
||||
+7
-7
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.transformers.contracts
|
||||
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.contracts.description.*
|
||||
@@ -65,7 +65,7 @@ class ConeEffectExtractor(
|
||||
FirContractsDslNames.CALLS_IN_PLACE -> {
|
||||
val reference = functionCall.arguments[0].accept(this, null) as? ConeValueParameterReference
|
||||
?: return null
|
||||
val kind = functionCall.arguments.getOrNull(1)?.parseInvocationKind() ?: InvocationKind.UNKNOWN
|
||||
val kind = functionCall.arguments.getOrNull(1)?.parseInvocationKind() ?: EventOccurrencesRange.UNKNOWN
|
||||
ConeCallsEffectDeclaration(reference, kind)
|
||||
}
|
||||
|
||||
@@ -165,14 +165,14 @@ class ConeEffectExtractor(
|
||||
return ConeIsInstancePredicate(arg, type, isNegated)
|
||||
}
|
||||
|
||||
private fun FirExpression.parseInvocationKind(): InvocationKind? {
|
||||
private fun FirExpression.parseInvocationKind(): EventOccurrencesRange? {
|
||||
if (this !is FirQualifiedAccessExpression) return null
|
||||
val resolvedId = toResolvedCallableSymbol()?.callableId ?: return null
|
||||
return when (resolvedId) {
|
||||
FirContractsDslNames.EXACTLY_ONCE_KIND -> InvocationKind.EXACTLY_ONCE
|
||||
FirContractsDslNames.AT_LEAST_ONCE_KIND -> InvocationKind.AT_LEAST_ONCE
|
||||
FirContractsDslNames.AT_MOST_ONCE_KIND -> InvocationKind.AT_MOST_ONCE
|
||||
FirContractsDslNames.UNKNOWN_KIND -> InvocationKind.UNKNOWN
|
||||
FirContractsDslNames.EXACTLY_ONCE_KIND -> EventOccurrencesRange.EXACTLY_ONCE
|
||||
FirContractsDslNames.AT_LEAST_ONCE_KIND -> EventOccurrencesRange.AT_LEAST_ONCE
|
||||
FirContractsDslNames.AT_MOST_ONCE_KIND -> EventOccurrencesRange.AT_MOST_ONCE
|
||||
FirContractsDslNames.UNKNOWN_KIND -> EventOccurrencesRange.UNKNOWN
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.declarations
|
||||
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.fir.FirLabel
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
@@ -37,7 +37,7 @@ abstract class FirAnonymousFunction : FirFunction<FirAnonymousFunction>, FirExpr
|
||||
abstract override val typeRef: FirTypeRef
|
||||
abstract override val symbol: FirAnonymousFunctionSymbol
|
||||
abstract val label: FirLabel?
|
||||
abstract val invocationKind: InvocationKind?
|
||||
abstract val eventOccurrencesRange: EventOccurrencesRange?
|
||||
abstract val isLambda: Boolean
|
||||
abstract override val typeParameters: List<FirTypeParameter>
|
||||
|
||||
@@ -53,7 +53,7 @@ abstract class FirAnonymousFunction : FirFunction<FirAnonymousFunction>, FirExpr
|
||||
|
||||
abstract override fun replaceTypeRef(newTypeRef: FirTypeRef)
|
||||
|
||||
abstract fun replaceInvocationKind(newInvocationKind: InvocationKind?)
|
||||
abstract fun replaceInvocationKind(newEventOccurrencesRange: EventOccurrencesRange?)
|
||||
|
||||
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirAnonymousFunction
|
||||
|
||||
|
||||
+3
-7
@@ -6,19 +6,16 @@
|
||||
package org.jetbrains.kotlin.fir.declarations.builder
|
||||
|
||||
import kotlin.contracts.*
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.fir.FirLabel
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder
|
||||
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationAttributes
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.FirFunctionBuilder
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirAnonymousFunctionImpl
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
||||
@@ -28,7 +25,6 @@ import org.jetbrains.kotlin.fir.references.impl.FirEmptyControlFlowGraphReferenc
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl
|
||||
import org.jetbrains.kotlin.fir.visitors.*
|
||||
|
||||
/*
|
||||
* This file was generated automatically
|
||||
@@ -49,7 +45,7 @@ class FirAnonymousFunctionBuilder : FirFunctionBuilder, FirAnnotationContainerBu
|
||||
override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null)
|
||||
lateinit var symbol: FirAnonymousFunctionSymbol
|
||||
var label: FirLabel? = null
|
||||
var invocationKind: InvocationKind? = null
|
||||
var eventOccurrencesRange: EventOccurrencesRange? = null
|
||||
var isLambda: Boolean by kotlin.properties.Delegates.notNull<Boolean>()
|
||||
val typeParameters: MutableList<FirTypeParameter> = mutableListOf()
|
||||
|
||||
@@ -67,7 +63,7 @@ class FirAnonymousFunctionBuilder : FirFunctionBuilder, FirAnnotationContainerBu
|
||||
typeRef,
|
||||
symbol,
|
||||
label,
|
||||
invocationKind,
|
||||
eventOccurrencesRange,
|
||||
isLambda,
|
||||
typeParameters,
|
||||
)
|
||||
|
||||
+4
-4
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.declarations.impl
|
||||
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.fir.FirLabel
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
@@ -40,7 +40,7 @@ internal class FirAnonymousFunctionImpl(
|
||||
override var typeRef: FirTypeRef,
|
||||
override val symbol: FirAnonymousFunctionSymbol,
|
||||
override var label: FirLabel?,
|
||||
override var invocationKind: InvocationKind?,
|
||||
override var eventOccurrencesRange: EventOccurrencesRange?,
|
||||
override val isLambda: Boolean,
|
||||
override val typeParameters: MutableList<FirTypeParameter>,
|
||||
) : FirAnonymousFunction() {
|
||||
@@ -122,7 +122,7 @@ internal class FirAnonymousFunctionImpl(
|
||||
typeRef = newTypeRef
|
||||
}
|
||||
|
||||
override fun replaceInvocationKind(newInvocationKind: InvocationKind?) {
|
||||
invocationKind = newInvocationKind
|
||||
override fun replaceInvocationKind(newInvocationKind: EventOccurrencesRange?) {
|
||||
eventOccurrencesRange = newInvocationKind
|
||||
}
|
||||
}
|
||||
|
||||
@@ -449,8 +449,8 @@ class FirRenderer(builder: StringBuilder, private val mode: RenderMode = RenderM
|
||||
anonymousFunction.valueParameters.renderParameters()
|
||||
print(": ")
|
||||
anonymousFunction.returnTypeRef.accept(this)
|
||||
if (anonymousFunction.invocationKind != null) {
|
||||
print(" <kind=${anonymousFunction.invocationKind}> ")
|
||||
if (anonymousFunction.eventOccurrencesRange != null) {
|
||||
print(" <kind=${anonymousFunction.eventOccurrencesRange}> ")
|
||||
}
|
||||
if (mode.renderLambdaBodies) {
|
||||
anonymousFunction.body?.renderBody()
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.contracts.description
|
||||
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
|
||||
/**
|
||||
* Effect with condition attached to it.
|
||||
@@ -41,7 +41,7 @@ class ConeReturnsEffectDeclaration(val value: ConeConstantReference) : ConeEffec
|
||||
* Effect which specifies, that during execution of subroutine, callable [valueParameterReference] will be invoked
|
||||
* [kind] amount of times, and will never be invoked after subroutine call is finished.
|
||||
*/
|
||||
class ConeCallsEffectDeclaration(val valueParameterReference: ConeValueParameterReference, val kind: InvocationKind) : ConeEffectDeclaration() {
|
||||
class ConeCallsEffectDeclaration(val valueParameterReference: ConeValueParameterReference, val kind: EventOccurrencesRange) : ConeEffectDeclaration() {
|
||||
override fun <R, D> accept(contractDescriptionVisitor: ConeContractDescriptionVisitor<R, D>, data: D): R =
|
||||
contractDescriptionVisitor.visitCallsEffectDeclaration(this, data)
|
||||
}
|
||||
+1
-1
@@ -266,7 +266,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
|
||||
parentArg(function, "F", anonymousFunction)
|
||||
+symbol("FirAnonymousFunctionSymbol")
|
||||
+field(label, nullable = true)
|
||||
+field(invocationKindType, nullable = true, withReplace = true).apply {
|
||||
+field(eventOccurrencesRangeType, nullable = true, withReplace = true).apply {
|
||||
isMutable = true
|
||||
}
|
||||
+booleanField("isLambda")
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.tree.generator
|
||||
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
@@ -25,7 +25,7 @@ val jumpTargetType = type("fir", "FirTarget")
|
||||
val constKindType = generatedType("expressions", "FirConstKind")
|
||||
val operationType = type("fir.expressions", "FirOperation")
|
||||
val classKindType = type(ClassKind::class)
|
||||
val invocationKindType = type(InvocationKind::class)
|
||||
val eventOccurrencesRangeType = type(EventOccurrencesRange::class)
|
||||
val varianceType = type(Variance::class)
|
||||
val nameType = type(Name::class)
|
||||
val visibilityType = type(Visibility::class)
|
||||
|
||||
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.cfg
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.PseudoValue
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.*
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
@@ -28,9 +28,9 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
|
||||
interface ControlFlowBuilder {
|
||||
// Subroutines
|
||||
fun enterSubroutine(subroutine: KtElement, invocationKind: InvocationKind? = null)
|
||||
fun enterSubroutine(subroutine: KtElement, eventOccurrencesRange: EventOccurrencesRange? = null)
|
||||
|
||||
fun exitSubroutine(subroutine: KtElement, invocationKind: InvocationKind? = null): Pseudocode
|
||||
fun exitSubroutine(subroutine: KtElement, eventOccurrencesRange: EventOccurrencesRange? = null): Pseudocode
|
||||
|
||||
val currentSubroutine: KtElement
|
||||
val returnSubroutine: KtElement
|
||||
@@ -50,7 +50,7 @@ interface ControlFlowBuilder {
|
||||
fun declareVariable(property: KtVariableDeclaration)
|
||||
fun declareFunction(subroutine: KtElement, pseudocode: Pseudocode)
|
||||
|
||||
fun declareInlinedFunction(subroutine: KtElement, pseudocode: Pseudocode, invocationKind: InvocationKind)
|
||||
fun declareInlinedFunction(subroutine: KtElement, pseudocode: Pseudocode, eventOccurrencesRange: EventOccurrencesRange)
|
||||
|
||||
fun declareEntryOrObject(entryOrObject: KtClassOrObject)
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.cfg
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.PseudoValue
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.*
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
@@ -139,12 +139,12 @@ abstract class ControlFlowBuilderAdapter : ControlFlowBuilder {
|
||||
delegateBuilder.exitTryFinally()
|
||||
}
|
||||
|
||||
override fun enterSubroutine(subroutine: KtElement, invocationKind: InvocationKind?) {
|
||||
delegateBuilder.enterSubroutine(subroutine, invocationKind)
|
||||
override fun enterSubroutine(subroutine: KtElement, eventOccurrencesRange: EventOccurrencesRange?) {
|
||||
delegateBuilder.enterSubroutine(subroutine, eventOccurrencesRange)
|
||||
}
|
||||
|
||||
override fun exitSubroutine(subroutine: KtElement, invocationKind: InvocationKind?): Pseudocode =
|
||||
delegateBuilder.exitSubroutine(subroutine, invocationKind)
|
||||
override fun exitSubroutine(subroutine: KtElement, eventOccurrencesRange: EventOccurrencesRange?): Pseudocode =
|
||||
delegateBuilder.exitSubroutine(subroutine, eventOccurrencesRange)
|
||||
|
||||
override val currentSubroutine: KtElement
|
||||
get() = delegateBuilder.currentSubroutine
|
||||
@@ -185,8 +185,8 @@ abstract class ControlFlowBuilderAdapter : ControlFlowBuilder {
|
||||
delegateBuilder.declareFunction(subroutine, pseudocode)
|
||||
}
|
||||
|
||||
override fun declareInlinedFunction(subroutine: KtElement, pseudocode: Pseudocode, invocationKind: InvocationKind) {
|
||||
delegateBuilder.declareInlinedFunction(subroutine, pseudocode, invocationKind)
|
||||
override fun declareInlinedFunction(subroutine: KtElement, pseudocode: Pseudocode, eventOccurrencesRange: EventOccurrencesRange) {
|
||||
delegateBuilder.declareInlinedFunction(subroutine, pseudocode, eventOccurrencesRange)
|
||||
}
|
||||
|
||||
override fun declareEntryOrObject(entryOrObject: KtClassOrObject) {
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.InstructionWithValu
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.MagicKind
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.contracts.description.canBeRevisited
|
||||
import org.jetbrains.kotlin.contracts.description.isDefinitelyVisited
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
@@ -79,8 +79,8 @@ class ControlFlowProcessor(
|
||||
return pseudocode
|
||||
}
|
||||
|
||||
private fun generate(subroutine: KtElement, invocationKind: InvocationKind? = null): Pseudocode {
|
||||
builder.enterSubroutine(subroutine, invocationKind)
|
||||
private fun generate(subroutine: KtElement, eventOccurrencesRange: EventOccurrencesRange? = null): Pseudocode {
|
||||
builder.enterSubroutine(subroutine, eventOccurrencesRange)
|
||||
val cfpVisitor = CFPVisitor(builder)
|
||||
if (subroutine is KtDeclarationWithBody && subroutine !is KtSecondaryConstructor) {
|
||||
val valueParameters = subroutine.valueParameters
|
||||
@@ -97,7 +97,7 @@ class ControlFlowProcessor(
|
||||
} else {
|
||||
cfpVisitor.generateInstructions(subroutine)
|
||||
}
|
||||
return builder.exitSubroutine(subroutine, invocationKind)
|
||||
return builder.exitSubroutine(subroutine, eventOccurrencesRange)
|
||||
}
|
||||
|
||||
private fun generateImplicitReturnValue(bodyExpression: KtExpression, subroutine: KtElement) {
|
||||
@@ -1035,11 +1035,11 @@ class ControlFlowProcessor(
|
||||
return parent.parent is KtDoWhileExpression
|
||||
}
|
||||
|
||||
private fun visitFunction(function: KtFunction, invocationKind: InvocationKind? = null) {
|
||||
if (invocationKind == null) {
|
||||
private fun visitFunction(function: KtFunction, eventOccurrencesRange: EventOccurrencesRange? = null) {
|
||||
if (eventOccurrencesRange == null) {
|
||||
processLocalDeclaration(function)
|
||||
} else {
|
||||
visitInlinedFunction(function, invocationKind)
|
||||
visitInlinedFunction(function, eventOccurrencesRange)
|
||||
}
|
||||
|
||||
val isAnonymousFunction = function is KtFunctionLiteral || function.name == null
|
||||
@@ -1048,7 +1048,7 @@ class ControlFlowProcessor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun visitInlinedFunction(lambdaFunctionLiteral: KtFunction, invocationKind: InvocationKind) {
|
||||
private fun visitInlinedFunction(lambdaFunctionLiteral: KtFunction, eventOccurrencesRange: EventOccurrencesRange) {
|
||||
// Defer emitting of inlined declaration
|
||||
deferredGeneratorsStack.peek().add({ builder ->
|
||||
val beforeDeclaration = builder.createUnboundLabel("before inlined declaration")
|
||||
@@ -1056,13 +1056,13 @@ class ControlFlowProcessor(
|
||||
|
||||
builder.bindLabel(beforeDeclaration)
|
||||
|
||||
if (!invocationKind.isDefinitelyVisited()) {
|
||||
if (!eventOccurrencesRange.isDefinitelyVisited()) {
|
||||
builder.nondeterministicJump(afterDeclaration, lambdaFunctionLiteral, null)
|
||||
}
|
||||
|
||||
generate(lambdaFunctionLiteral, invocationKind)
|
||||
generate(lambdaFunctionLiteral, eventOccurrencesRange)
|
||||
|
||||
if (invocationKind.canBeRevisited()) {
|
||||
if (eventOccurrencesRange.canBeRevisited()) {
|
||||
builder.nondeterministicJump(beforeDeclaration, lambdaFunctionLiteral, null)
|
||||
}
|
||||
|
||||
|
||||
+11
-11
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.*
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.jumps.*
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.*
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
@@ -64,9 +64,9 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
||||
return worker
|
||||
}
|
||||
|
||||
override fun enterSubroutine(subroutine: KtElement, invocationKind: InvocationKind?) {
|
||||
override fun enterSubroutine(subroutine: KtElement, eventOccurrencesRange: EventOccurrencesRange?) {
|
||||
val builder = builder
|
||||
val shouldInlnie = invocationKind != null
|
||||
val shouldInlnie = eventOccurrencesRange != null
|
||||
if (builder != null && subroutine is KtFunctionLiteral) {
|
||||
pushBuilder(subroutine, builder.returnSubroutine, shouldInlnie)
|
||||
} else {
|
||||
@@ -76,16 +76,16 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
||||
delegateBuilder.enterSubroutine(subroutine)
|
||||
}
|
||||
|
||||
override fun exitSubroutine(subroutine: KtElement, invocationKind: InvocationKind?): Pseudocode {
|
||||
super.exitSubroutine(subroutine, invocationKind)
|
||||
override fun exitSubroutine(subroutine: KtElement, eventOccurrencesRange: EventOccurrencesRange?): Pseudocode {
|
||||
super.exitSubroutine(subroutine, eventOccurrencesRange)
|
||||
delegateBuilder.exitBlockScope(subroutine)
|
||||
val worker = popBuilder()
|
||||
if (!builders.empty()) {
|
||||
val builder = builders.peek()
|
||||
if (invocationKind == null) {
|
||||
if (eventOccurrencesRange == null) {
|
||||
builder.declareFunction(subroutine, worker.pseudocode)
|
||||
} else {
|
||||
builder.declareInlinedFunction(subroutine, worker.pseudocode, invocationKind)
|
||||
builder.declareInlinedFunction(subroutine, worker.pseudocode, eventOccurrencesRange)
|
||||
}
|
||||
}
|
||||
return worker.pseudocode
|
||||
@@ -154,7 +154,7 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
||||
override val currentLoop: KtLoopExpression?
|
||||
get() = if (loopInfo.empty()) null else loopInfo.peek().element
|
||||
|
||||
override fun enterSubroutine(subroutine: KtElement, invocationKind: InvocationKind?) {
|
||||
override fun enterSubroutine(subroutine: KtElement, eventOccurrencesRange: EventOccurrencesRange?) {
|
||||
val blockInfo = SubroutineInfo(
|
||||
subroutine,
|
||||
/* entry point */ createUnboundLabel(),
|
||||
@@ -215,7 +215,7 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun exitSubroutine(subroutine: KtElement, invocationKind: InvocationKind?): Pseudocode {
|
||||
override fun exitSubroutine(subroutine: KtElement, eventOccurrencesRange: EventOccurrencesRange?): Pseudocode {
|
||||
getSubroutineExitPoint(subroutine)?.let { bindLabel(it) }
|
||||
pseudocode.addExitInstruction(SubroutineExitInstruction(subroutine, currentScope, false))
|
||||
bindLabel(error)
|
||||
@@ -273,8 +273,8 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
||||
add(LocalFunctionDeclarationInstruction(subroutine, pseudocode, currentScope))
|
||||
}
|
||||
|
||||
override fun declareInlinedFunction(subroutine: KtElement, pseudocode: Pseudocode, invocationKind: InvocationKind) {
|
||||
add(InlinedLocalFunctionDeclarationInstruction(subroutine, pseudocode, currentScope, invocationKind))
|
||||
override fun declareInlinedFunction(subroutine: KtElement, pseudocode: Pseudocode, eventOccurrencesRange: EventOccurrencesRange) {
|
||||
add(InlinedLocalFunctionDeclarationInstruction(subroutine, pseudocode, currentScope, eventOccurrencesRange))
|
||||
}
|
||||
|
||||
override fun declareEntryOrObject(entryOrObject: KtClassOrObject) {
|
||||
|
||||
+2
-2
@@ -21,14 +21,14 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.BlockScope
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionImpl
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitor
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitorWithResult
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
|
||||
class InlinedLocalFunctionDeclarationInstruction(
|
||||
element: KtElement,
|
||||
body: Pseudocode,
|
||||
blockScope: BlockScope,
|
||||
val kind: InvocationKind
|
||||
val kind: EventOccurrencesRange
|
||||
) : LocalFunctionDeclarationInstruction(element, body, blockScope) {
|
||||
override fun createCopy(): InstructionImpl = InlinedLocalFunctionDeclarationInstruction(element, body, blockScope, kind)
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ class ContractDeserializerImpl(
|
||||
val invocationKind = if (proto.hasKind())
|
||||
proto.kind.toDescriptorInvocationKind() ?: return null
|
||||
else
|
||||
InvocationKind.UNKNOWN
|
||||
EventOccurrencesRange.UNKNOWN
|
||||
CallsEffectDeclaration(callable, invocationKind)
|
||||
}
|
||||
}
|
||||
@@ -165,10 +165,10 @@ class ContractDeserializerImpl(
|
||||
BooleanVariableReference(parameterDescriptor)
|
||||
}
|
||||
|
||||
private fun ProtoBuf.Effect.InvocationKind.toDescriptorInvocationKind(): InvocationKind? = when (this) {
|
||||
ProtoBuf.Effect.InvocationKind.AT_MOST_ONCE -> InvocationKind.AT_MOST_ONCE
|
||||
ProtoBuf.Effect.InvocationKind.EXACTLY_ONCE -> InvocationKind.EXACTLY_ONCE
|
||||
ProtoBuf.Effect.InvocationKind.AT_LEAST_ONCE -> InvocationKind.AT_LEAST_ONCE
|
||||
private fun ProtoBuf.Effect.InvocationKind.toDescriptorInvocationKind(): EventOccurrencesRange? = when (this) {
|
||||
ProtoBuf.Effect.InvocationKind.AT_MOST_ONCE -> EventOccurrencesRange.AT_MOST_ONCE
|
||||
ProtoBuf.Effect.InvocationKind.EXACTLY_ONCE -> EventOccurrencesRange.EXACTLY_ONCE
|
||||
ProtoBuf.Effect.InvocationKind.AT_LEAST_ONCE -> EventOccurrencesRange.AT_LEAST_ONCE
|
||||
}
|
||||
|
||||
private fun extractType(proto: ProtoBuf.Expression): KotlinType? {
|
||||
|
||||
+7
-7
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.contracts.parsing.effects
|
||||
|
||||
import org.jetbrains.kotlin.contracts.description.CallsEffectDeclaration
|
||||
import org.jetbrains.kotlin.contracts.description.EffectDeclaration
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.contracts.parsing.*
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
@@ -45,7 +45,7 @@ internal class PsiCallsEffectParser(
|
||||
val kindArgument = resolvedCall.valueArgumentsByIndex?.getOrNull(1)
|
||||
|
||||
val kind = when (kindArgument) {
|
||||
is DefaultValueArgument -> InvocationKind.UNKNOWN
|
||||
is DefaultValueArgument -> EventOccurrencesRange.UNKNOWN
|
||||
is ExpressionValueArgument -> kindArgument.valueArgument?.getArgumentExpression()?.toInvocationKind(callContext.bindingContext)
|
||||
else -> null
|
||||
}
|
||||
@@ -59,15 +59,15 @@ internal class PsiCallsEffectParser(
|
||||
return CallsEffectDeclaration(lambda, kind)
|
||||
}
|
||||
|
||||
private fun KtExpression.toInvocationKind(bindingContext: BindingContext): InvocationKind? {
|
||||
private fun KtExpression.toInvocationKind(bindingContext: BindingContext): EventOccurrencesRange? {
|
||||
val descriptor = this.getResolvedCall(bindingContext)?.resultingDescriptor ?: return null
|
||||
if (!descriptor.parents.first().isInvocationKindEnum()) return null
|
||||
|
||||
return when (descriptor.fqNameSafe.shortName()) {
|
||||
ContractsDslNames.AT_MOST_ONCE_KIND -> InvocationKind.AT_MOST_ONCE
|
||||
ContractsDslNames.EXACTLY_ONCE_KIND -> InvocationKind.EXACTLY_ONCE
|
||||
ContractsDslNames.AT_LEAST_ONCE_KIND -> InvocationKind.AT_LEAST_ONCE
|
||||
ContractsDslNames.UNKNOWN_KIND -> InvocationKind.UNKNOWN
|
||||
ContractsDslNames.AT_MOST_ONCE_KIND -> EventOccurrencesRange.AT_MOST_ONCE
|
||||
ContractsDslNames.EXACTLY_ONCE_KIND -> EventOccurrencesRange.EXACTLY_ONCE
|
||||
ContractsDslNames.AT_LEAST_ONCE_KIND -> EventOccurrencesRange.AT_LEAST_ONCE
|
||||
ContractsDslNames.UNKNOWN_KIND -> EventOccurrencesRange.UNKNOWN
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
import org.jetbrains.kotlin.cfg.LeakingThisDescriptor;
|
||||
import org.jetbrains.kotlin.cfg.TailRecursionKind;
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind;
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange;
|
||||
import org.jetbrains.kotlin.contracts.model.Computation;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||
@@ -221,7 +221,7 @@ public interface BindingContext {
|
||||
WritableSlice<PropertyDescriptor, Boolean> IS_UNINITIALIZED = Slices.createSimpleSetSlice();
|
||||
WritableSlice<PropertyDescriptor, Boolean> MUST_BE_LATEINIT = Slices.createSimpleSetSlice();
|
||||
|
||||
WritableSlice<KtLambdaExpression, InvocationKind> LAMBDA_INVOCATIONS = Slices.createSimpleSlice();
|
||||
WritableSlice<KtLambdaExpression, EventOccurrencesRange> LAMBDA_INVOCATIONS = Slices.createSimpleSlice();
|
||||
|
||||
WritableSlice<KtLambdaExpression, Boolean> BLOCK = new SetSlice<KtLambdaExpression>(DO_NOTHING) {
|
||||
@Override
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.resolve.calls.checkers
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.contracts.description.CallsEffectDeclaration
|
||||
import org.jetbrains.kotlin.contracts.description.ContractProviderKey
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
@@ -147,7 +147,7 @@ class CapturingInClosureChecker : CallChecker {
|
||||
val contractDescription = function.getUserData(ContractProviderKey)?.getContractDescription() ?: return false
|
||||
val effect = contractDescription.effects.filterIsInstance<CallsEffectDeclaration>()
|
||||
.find { it.variableReference.descriptor == parameter.original } ?: return false
|
||||
return effect.kind == InvocationKind.EXACTLY_ONCE
|
||||
return effect.kind == EventOccurrencesRange.EXACTLY_ONCE
|
||||
}
|
||||
|
||||
private fun isExactlyOnceContract(bindingContext: BindingContext, argument: KtFunction): Boolean {
|
||||
|
||||
@@ -53,7 +53,7 @@ class ReturnsEffectDeclaration(val value: ConstantReference) : EffectDeclaration
|
||||
* Effect which specifies, that during execution of subroutine, callable [variableReference] will be invoked
|
||||
* [kind] amount of times, and will never be invoked after subroutine call is finished.
|
||||
*/
|
||||
class CallsEffectDeclaration(val variableReference: VariableReference, val kind: InvocationKind) : EffectDeclaration {
|
||||
class CallsEffectDeclaration(val variableReference: VariableReference, val kind: EventOccurrencesRange) : EffectDeclaration {
|
||||
override fun <R, D> accept(contractDescriptionVisitor: ContractDescriptionVisitor<R, D>, data: D): R =
|
||||
contractDescriptionVisitor.visitCallsEffectDeclaration(this, data)
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.contracts.description
|
||||
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
enum class EventOccurrencesRange(private val left: Int, private val right: Int) {
|
||||
ZERO(0, 0), // 0..0
|
||||
AT_MOST_ONCE(0, 1), // 0..1
|
||||
EXACTLY_ONCE(1, 1), // 1..1
|
||||
AT_LEAST_ONCE(1, 2), // 1..*
|
||||
UNKNOWN(0, 2); // 0..*
|
||||
|
||||
companion object {
|
||||
private fun fromRange(left: Int, right: Int): EventOccurrencesRange = when (min(left, 1) to min(right, 2)) {
|
||||
0 to 0 -> ZERO
|
||||
0 to 1 -> AT_MOST_ONCE
|
||||
1 to 1 -> EXACTLY_ONCE
|
||||
1 to 2 -> AT_LEAST_ONCE
|
||||
0 to 2 -> UNKNOWN
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
|
||||
fun or(x: EventOccurrencesRange, y: EventOccurrencesRange): EventOccurrencesRange = fromRange(min(x.left, y.left), max(x.right, y.right))
|
||||
|
||||
fun plus(x: EventOccurrencesRange, y: EventOccurrencesRange): EventOccurrencesRange = fromRange(x.left + y.left, x.right + y.right)
|
||||
}
|
||||
|
||||
infix fun or(other: EventOccurrencesRange): EventOccurrencesRange = Companion.or(this, other)
|
||||
operator fun plus(other: EventOccurrencesRange): EventOccurrencesRange = Companion.plus(this, other)
|
||||
}
|
||||
|
||||
fun EventOccurrencesRange.isDefinitelyVisited(): Boolean = this == EventOccurrencesRange.EXACTLY_ONCE || this == EventOccurrencesRange.AT_LEAST_ONCE
|
||||
fun EventOccurrencesRange.canBeRevisited(): Boolean = this == EventOccurrencesRange.UNKNOWN || this == EventOccurrencesRange.AT_LEAST_ONCE
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.contracts.description
|
||||
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
enum class InvocationKind(private val left: Int, private val right: Int) {
|
||||
ZERO(0, 0), // 0..0
|
||||
AT_MOST_ONCE(0, 1), // 0..1
|
||||
EXACTLY_ONCE(1, 1), // 1..1
|
||||
AT_LEAST_ONCE(1, 2), // 1..*
|
||||
UNKNOWN(0, 2); // 0..*
|
||||
|
||||
companion object {
|
||||
private fun fromRange(left: Int, right: Int): InvocationKind = when (min(left, 1) to min(right, 2)) {
|
||||
0 to 0 -> ZERO
|
||||
0 to 1 -> AT_MOST_ONCE
|
||||
1 to 1 -> EXACTLY_ONCE
|
||||
1 to 2 -> AT_LEAST_ONCE
|
||||
0 to 2 -> UNKNOWN
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
|
||||
fun or(x: InvocationKind, y: InvocationKind): InvocationKind = fromRange(min(x.left, y.left), max(x.right, y.right))
|
||||
|
||||
fun and(x: InvocationKind, y: InvocationKind): InvocationKind = fromRange(x.left + y.left, x.right + y.right)
|
||||
}
|
||||
|
||||
infix fun or(other: InvocationKind): InvocationKind = Companion.or(this, other)
|
||||
infix fun and(other: InvocationKind): InvocationKind = Companion.and(this, other)
|
||||
}
|
||||
|
||||
fun InvocationKind.isDefinitelyVisited(): Boolean = this == InvocationKind.EXACTLY_ONCE || this == InvocationKind.AT_LEAST_ONCE
|
||||
fun InvocationKind.canBeRevisited(): Boolean = this == InvocationKind.UNKNOWN || this == InvocationKind.AT_LEAST_ONCE
|
||||
@@ -16,12 +16,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.contracts.model.structure
|
||||
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.contracts.model.ESEffect
|
||||
import org.jetbrains.kotlin.contracts.model.ESValue
|
||||
import org.jetbrains.kotlin.contracts.model.SimpleEffect
|
||||
|
||||
data class ESCalls(val callable: ESValue, val kind: InvocationKind) : SimpleEffect() {
|
||||
data class ESCalls(val callable: ESValue, val kind: EventOccurrencesRange) : SimpleEffect() {
|
||||
override fun isImplies(other: ESEffect): Boolean? {
|
||||
if (other !is ESCalls) return null
|
||||
|
||||
|
||||
@@ -188,10 +188,10 @@ class ContractSerializer {
|
||||
}
|
||||
}
|
||||
|
||||
private fun invocationKindProtobufEnum(kind: InvocationKind): ProtoBuf.Effect.InvocationKind? = when (kind) {
|
||||
InvocationKind.AT_MOST_ONCE -> ProtoBuf.Effect.InvocationKind.AT_MOST_ONCE
|
||||
InvocationKind.EXACTLY_ONCE -> ProtoBuf.Effect.InvocationKind.EXACTLY_ONCE
|
||||
InvocationKind.AT_LEAST_ONCE -> ProtoBuf.Effect.InvocationKind.AT_LEAST_ONCE
|
||||
private fun invocationKindProtobufEnum(kind: EventOccurrencesRange): ProtoBuf.Effect.InvocationKind? = when (kind) {
|
||||
EventOccurrencesRange.AT_MOST_ONCE -> ProtoBuf.Effect.InvocationKind.AT_MOST_ONCE
|
||||
EventOccurrencesRange.EXACTLY_ONCE -> ProtoBuf.Effect.InvocationKind.EXACTLY_ONCE
|
||||
EventOccurrencesRange.AT_LEAST_ONCE -> ProtoBuf.Effect.InvocationKind.AT_LEAST_ONCE
|
||||
else -> null
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user