[cls] write contracts information to cls stubs

^ KTIJ-24665
this information would be used to create resolved FirElements from stubs,
so no ProtoBuf would be kept in memory
This commit is contained in:
Anna Kozlova
2023-04-05 17:12:30 +02:00
committed by Space Team
parent 9d4db72d72
commit 4fe239375f
44 changed files with 1182 additions and 534 deletions
@@ -0,0 +1,22 @@
/*
* Copyright 2010-2023 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
interface KtContractDescriptionElement<Type, Diagnostic> {
fun <R, D> accept(contractDescriptionVisitor: KtContractDescriptionVisitor<R, D, Type, Diagnostic>, data: D): R
val erroneous: Boolean
}
abstract class KtEffectDeclaration<Type, Diagnostic> : KtContractDescriptionElement<Type, Diagnostic> {
override fun <R, D> accept(contractDescriptionVisitor: KtContractDescriptionVisitor<R, D, Type, Diagnostic>, data: D): R =
contractDescriptionVisitor.visitEffectDeclaration(this, data)
}
interface KtBooleanExpression<Type, Diagnostic> : KtContractDescriptionElement<Type, Diagnostic> {
override fun <R, D> accept(contractDescriptionVisitor: KtContractDescriptionVisitor<R, D, Type, Diagnostic>, data: D): R =
contractDescriptionVisitor.visitBooleanExpression(this, data)
}
@@ -0,0 +1,69 @@
/*
* Copyright 2010-2023 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
abstract class KtContractDescriptionVisitor<out R, in D, Type, Diagnostic> {
open fun visitContractDescriptionElement(contractDescriptionElement: KtContractDescriptionElement<Type, Diagnostic>, data: D): R {
throw IllegalStateException("Top of hierarchy reached, no overloads were found for element: $contractDescriptionElement")
}
// Effects
open fun visitEffectDeclaration(effectDeclaration: KtEffectDeclaration<Type, Diagnostic>, data: D): R = visitContractDescriptionElement(effectDeclaration, data)
open fun visitConditionalEffectDeclaration(conditionalEffect: KtConditionalEffectDeclaration<Type, Diagnostic>, data: D): R =
visitEffectDeclaration(conditionalEffect, data)
open fun visitReturnsEffectDeclaration(returnsEffect: KtReturnsEffectDeclaration<Type, Diagnostic>, data: D): R =
visitEffectDeclaration(returnsEffect, data)
open fun visitCallsEffectDeclaration(callsEffect: KtCallsEffectDeclaration<Type, Diagnostic>, data: D): R =
visitEffectDeclaration(callsEffect, data)
open fun visitErroneousCallsEffectDeclaration(callsEffect: KtErroneousCallsEffectDeclaration<Type, Diagnostic>, data: D): R =
visitCallsEffectDeclaration(callsEffect, data)
// Expressions
open fun visitBooleanExpression(booleanExpression: KtBooleanExpression<Type, Diagnostic>, data: D): R =
visitContractDescriptionElement(booleanExpression, data)
open fun visitLogicalBinaryOperationContractExpression(binaryLogicExpression: KtBinaryLogicExpression<Type, Diagnostic>, data: D): R =
visitBooleanExpression(binaryLogicExpression, data)
open fun visitLogicalNot(logicalNot: KtLogicalNot<Type, Diagnostic>, data: D): R = visitBooleanExpression(logicalNot, data)
open fun visitIsInstancePredicate(isInstancePredicate: KtIsInstancePredicate<Type, Diagnostic>, data: D): R =
visitBooleanExpression(isInstancePredicate, data)
open fun visitErroneousIsInstancePredicate(isInstancePredicate: KtErroneousIsInstancePredicate<Type, Diagnostic>, data: D): R =
visitIsInstancePredicate(isInstancePredicate, data)
open fun visitIsNullPredicate(isNullPredicate: KtIsNullPredicate<Type, Diagnostic>, data: D): R = visitBooleanExpression(isNullPredicate, data)
// Values
open fun visitValue(value: KtContractDescriptionValue<Type, Diagnostic>, data: D): R = visitContractDescriptionElement(value, data)
open fun visitConstantDescriptor(constantReference: KtConstantReference<Type, Diagnostic>, data: D): R = visitValue(constantReference, data)
open fun visitBooleanConstantDescriptor(booleanConstantDescriptor: KtBooleanConstantReference<Type, Diagnostic>, data: D): R =
visitConstantDescriptor(booleanConstantDescriptor, data)
open fun visitErroneousConstantReference(erroneousConstantReference: KtErroneousConstantReference<Type, Diagnostic>, data: D): R =
visitConstantDescriptor(erroneousConstantReference, data)
open fun visitValueParameterReference(valueParameterReference: KtValueParameterReference<Type, Diagnostic>, data: D): R =
visitValue(valueParameterReference, data)
open fun visitBooleanValueParameterReference(booleanValueParameterReference: KtBooleanValueParameterReference<Type, Diagnostic>, data: D): R =
visitValueParameterReference(booleanValueParameterReference, data)
open fun visitErroneousValueParameterReference(valueParameterReference: KtErroneousValueParameterReference<Type, Diagnostic>, data: D): R =
visitValueParameterReference(valueParameterReference, data)
// Error
open fun visitErroneousElement(element: KtErroneousContractElement<Type, Diagnostic>, data: D): R =
visitContractDescriptionElement(element, data)
}
@@ -0,0 +1,71 @@
/*
* Copyright 2010-2023 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
/**
* Effect with condition attached to it.
*
* [condition] is some expression, which result-type is Boolean, and clause should
* be interpreted as: "if [effect] took place then [condition]-expression is
* guaranteed to be true"
*
* NB. [effect] and [condition] connected with implication in math logic sense:
* [effect] => [condition]. In particular this means that:
* - there can be multiple ways how [effect] can be produced, but for any of them
* [condition] holds.
* - if [effect] wasn't observed, we *can't* reason that [condition] is false
* - if [condition] is true, we *can't* reason that [effect] will be observed.
*/
class KtConditionalEffectDeclaration<Type, Diagnostic>(
val effect: KtEffectDeclaration<Type, Diagnostic>,
val condition: KtBooleanExpression<Type, Diagnostic>
) : KtEffectDeclaration<Type, Diagnostic>() {
override val erroneous: Boolean
get() = effect.erroneous || condition.erroneous
override fun <R, D> accept(contractDescriptionVisitor: KtContractDescriptionVisitor<R, D, Type, Diagnostic>, data: D): R =
contractDescriptionVisitor.visitConditionalEffectDeclaration(this, data)
}
/**
* Effect which specifies that subroutine returns some particular value
*/
class KtReturnsEffectDeclaration<Type, Diagnostic>(val value: KtConstantReference<Type, Diagnostic>) :
KtEffectDeclaration<Type, Diagnostic>() {
override val erroneous: Boolean
get() = value.erroneous
override fun <R, D> accept(contractDescriptionVisitor: KtContractDescriptionVisitor<R, D, Type, Diagnostic>, data: D): R =
contractDescriptionVisitor.visitReturnsEffectDeclaration(this, data)
}
/**
* 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.
*/
open class KtCallsEffectDeclaration<Type, Diagnostic>(
val valueParameterReference: KtValueParameterReference<Type, Diagnostic>,
val kind: EventOccurrencesRange
) : KtEffectDeclaration<Type, Diagnostic>() {
override val erroneous: Boolean
get() = valueParameterReference.erroneous
override fun <R, D> accept(contractDescriptionVisitor: KtContractDescriptionVisitor<R, D, Type, Diagnostic>, data: D): R =
contractDescriptionVisitor.visitCallsEffectDeclaration(this, data)
}
class KtErroneousCallsEffectDeclaration<Type, Diagnostic>(
valueParameterReference: KtValueParameterReference<Type, Diagnostic>,
val diagnostic: Diagnostic
) : KtCallsEffectDeclaration<Type, Diagnostic>(valueParameterReference, EventOccurrencesRange.UNKNOWN) {
override val erroneous: Boolean
get() = true
override fun <R, D> accept(contractDescriptionVisitor: KtContractDescriptionVisitor<R, D, Type, Diagnostic>, data: D): R =
contractDescriptionVisitor.visitErroneousCallsEffectDeclaration(this, data)
}
@@ -0,0 +1,17 @@
/*
* Copyright 2010-2023 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
class KtErroneousContractElement<Type, Diagnostic>(
val diagnostic: Diagnostic
) : KtEffectDeclaration<Type, Diagnostic>(), KtBooleanExpression<Type, Diagnostic>, KtContractDescriptionValue<Type, Diagnostic> {
override val erroneous: Boolean
get() = true
override fun <R, D> accept(contractDescriptionVisitor: KtContractDescriptionVisitor<R, D, Type, Diagnostic>, data: D): R {
return contractDescriptionVisitor.visitErroneousElement(this, data)
}
}
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2023 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
class KtBinaryLogicExpression<Type, Diagnostic>(
val left: KtBooleanExpression<Type, Diagnostic>,
val right: KtBooleanExpression<Type, Diagnostic>,
val kind: LogicOperationKind
) : KtBooleanExpression<Type, Diagnostic> {
override val erroneous: Boolean
get() = left.erroneous || right.erroneous
override fun <R, D> accept(contractDescriptionVisitor: KtContractDescriptionVisitor<R, D, Type, Diagnostic>, data: D): R {
return contractDescriptionVisitor.visitLogicalBinaryOperationContractExpression(this, data)
}
}
class KtLogicalNot<Type, Diagnostic>(val arg: KtBooleanExpression<Type, Diagnostic>) : KtBooleanExpression<Type, Diagnostic> {
override val erroneous: Boolean
get() = arg.erroneous
override fun <R, D> accept(contractDescriptionVisitor: KtContractDescriptionVisitor<R, D, Type, Diagnostic>, data: D): R =
contractDescriptionVisitor.visitLogicalNot(this, data)
}
@@ -0,0 +1,43 @@
/*
* Copyright 2010-2023 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
open class KtIsInstancePredicate<Type, Diagnostic>(val arg: KtValueParameterReference<Type, Diagnostic>, val type: Type, val isNegated: Boolean) :
KtBooleanExpression<Type, Diagnostic> {
override val erroneous: Boolean
get() = arg.erroneous
override fun <R, D> accept(contractDescriptionVisitor: KtContractDescriptionVisitor<R, D, Type, Diagnostic>, data: D): R =
contractDescriptionVisitor.visitIsInstancePredicate(this, data)
fun negated(): KtIsInstancePredicate<Type, Diagnostic> =
KtIsInstancePredicate(arg, type, isNegated.not())
}
class KtErroneousIsInstancePredicate<Type, Diagnostic>(
arg: KtValueParameterReference<Type, Diagnostic>,
type: Type,
isNegated: Boolean,
val diagnostic: Diagnostic
) : KtIsInstancePredicate<Type, Diagnostic>(arg, type, isNegated) {
override val erroneous: Boolean
get() = true
override fun <R, D> accept(contractDescriptionVisitor: KtContractDescriptionVisitor<R, D, Type, Diagnostic>, data: D): R =
contractDescriptionVisitor.visitErroneousIsInstancePredicate(this, data)
}
class KtIsNullPredicate<Type, Diagnostic>(val arg: KtValueParameterReference<Type, Diagnostic>, val isNegated: Boolean) :
KtBooleanExpression<Type, Diagnostic> {
override val erroneous: Boolean
get() = arg.erroneous
override fun <R, D> accept(contractDescriptionVisitor: KtContractDescriptionVisitor<R, D, Type, Diagnostic>, data: D): R =
contractDescriptionVisitor.visitIsNullPredicate(this, data)
fun negated(): KtIsNullPredicate<Type, Diagnostic> =
KtIsNullPredicate(arg, isNegated.not())
}
@@ -0,0 +1,64 @@
/*
* Copyright 2010-2023 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
interface KtContractDescriptionValue<Type, Diagnostic> : KtContractDescriptionElement<Type, Diagnostic> {
override fun <R, D> accept(contractDescriptionVisitor: KtContractDescriptionVisitor<R, D, Type, Diagnostic>, data: D): R =
contractDescriptionVisitor.visitValue(this, data)
}
open class KtConstantReference<Type, Diagnostic>(val name: String) : KtContractDescriptionValue<Type, Diagnostic> {
override val erroneous: Boolean
get() = false
override fun <R, D> accept(contractDescriptionVisitor: KtContractDescriptionVisitor<R, D, Type, Diagnostic>, data: D): R =
contractDescriptionVisitor.visitConstantDescriptor(this, data)
}
class KtBooleanConstantReference<Type, Diagnostic>(name: String) : KtConstantReference<Type, Diagnostic>(name),
KtBooleanExpression<Type, Diagnostic> {
override fun <R, D> accept(contractDescriptionVisitor: KtContractDescriptionVisitor<R, D, Type, Diagnostic>, data: D): R =
contractDescriptionVisitor.visitBooleanConstantDescriptor(this, data)
}
class KtErroneousConstantReference<Type, Diagnostic>(val diagnostic: Diagnostic) : KtConstantReference<Type, Diagnostic>("ERROR") {
override val erroneous: Boolean
get() = true
override fun <R, D> accept(contractDescriptionVisitor: KtContractDescriptionVisitor<R, D, Type, Diagnostic>, data: D): R =
contractDescriptionVisitor.visitErroneousConstantReference(this, data)
}
/*
* Index of value parameter of function
* -1 means that it is reference to extension receiver
*/
open class KtValueParameterReference<Type, Diagnostic>(val parameterIndex: Int, val name: String) :
KtContractDescriptionValue<Type, Diagnostic> {
init {
assert(parameterIndex >= -1)
}
override val erroneous: Boolean
get() = false
override fun <R, D> accept(contractDescriptionVisitor: KtContractDescriptionVisitor<R, D, Type, Diagnostic>, data: D): R =
contractDescriptionVisitor.visitValueParameterReference(this, data)
}
class KtBooleanValueParameterReference<Type, Diagnostic>(parameterIndex: Int, name: String) : KtValueParameterReference<Type, Diagnostic>(parameterIndex, name),
KtBooleanExpression<Type, Diagnostic> {
override fun <R, D> accept(contractDescriptionVisitor: KtContractDescriptionVisitor<R, D, Type, Diagnostic>, data: D): R =
contractDescriptionVisitor.visitBooleanValueParameterReference(this, data)
}
class KtErroneousValueParameterReference<Type, Diagnostic>(val diagnostic: Diagnostic) : KtValueParameterReference<Type, Diagnostic>(Int.MAX_VALUE, "ERROR") {
override val erroneous: Boolean
get() = true
override fun <R, D> accept(contractDescriptionVisitor: KtContractDescriptionVisitor<R, D, Type, Diagnostic>, data: D): R =
contractDescriptionVisitor.visitErroneousValueParameterReference(this, data)
}
@@ -0,0 +1,10 @@
/*
* Copyright 2010-2023 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
enum class LogicOperationKind(val token: String) {
AND("&&"), OR("||")
}