[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:
Vendored
+77
@@ -0,0 +1,77 @@
|
||||
// JVM_FILE_NAME: ContractsKt
|
||||
|
||||
@file:OptIn(ExperimentalContracts::class)
|
||||
package test
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun myRequire(x: Boolean) {
|
||||
contract {
|
||||
returns() implies x
|
||||
}
|
||||
}
|
||||
|
||||
fun <R> call_InPlace(block: () -> R): R {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
fun isNull(obj: Any?): Boolean {
|
||||
contract {
|
||||
returns(true) implies (obj != null)
|
||||
}
|
||||
return obj != null
|
||||
}
|
||||
|
||||
fun isNotNull(foo: Any?): Any? {
|
||||
contract {
|
||||
returnsNotNull() implies (foo != null)
|
||||
}
|
||||
return foo
|
||||
}
|
||||
|
||||
fun isString(foo: Any?): String? {
|
||||
contract {
|
||||
returnsNotNull() implies (foo is String)
|
||||
}
|
||||
return foo as? String
|
||||
}
|
||||
|
||||
fun isNotString(foo: Any?): String? {
|
||||
contract {
|
||||
returnsNotNull() implies (foo !is String)
|
||||
}
|
||||
return if (foo is String) null else "not a string"
|
||||
}
|
||||
|
||||
fun String?.asSafe(): String? {
|
||||
contract {
|
||||
returnsNotNull() implies (this@asSafe != null)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
fun isStringCheck(x: Any?): Any? {
|
||||
contract {
|
||||
returns(true) implies (x is Comparable<*> || x is CharSequence)
|
||||
}
|
||||
|
||||
return x is String
|
||||
}
|
||||
|
||||
fun isStringOrNumber(x: Any?): Any? {
|
||||
contract {
|
||||
returns(true) implies (x is Comparable<*> && (x is CharSequence || x is Number))
|
||||
}
|
||||
|
||||
return x is String || x is Int
|
||||
}
|
||||
|
||||
inline fun <reified T : Number> T?.test0(): Boolean {
|
||||
contract {
|
||||
returns(true) implies (this@test0 is T)
|
||||
}
|
||||
return this is T
|
||||
}
|
||||
Vendored
+173
@@ -0,0 +1,173 @@
|
||||
PsiJetFileStubImpl[package=test]
|
||||
KotlinStub$PACKAGE_DIRECTIVE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=test]
|
||||
KotlinStub$IMPORT_LIST
|
||||
KotlinStub$FUN[fqName=test.call_InPlace, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=true, isExtension=false, isTopLevel=true, mayHaveContract=true, name=call_InPlace]
|
||||
effect:CallsInPlace(param(0), EXACTLY_ONCE)
|
||||
KotlinStub$MODIFIER_LIST[public]
|
||||
KotlinStub$TYPE_PARAMETER_LIST
|
||||
KotlinStub$TYPE_PARAMETER[fqName=null, isInVariance=false, isOutVariance=false, name=R]
|
||||
KotlinStub$VALUE_PARAMETER_LIST
|
||||
KotlinStub$VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=block]
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$FUNCTION_TYPE
|
||||
KotlinStub$VALUE_PARAMETER_LIST
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=R]
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=R]
|
||||
KotlinStub$FUN[fqName=test.isNotNull, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=true, mayHaveContract=true, name=isNotNull]
|
||||
effect:Returns(NOT_NULL) -> param(0) != null
|
||||
KotlinStub$MODIFIER_LIST[public]
|
||||
KotlinStub$VALUE_PARAMETER_LIST
|
||||
KotlinStub$VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=foo]
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$NULLABLE_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin]
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=Any]
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$NULLABLE_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin]
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=Any]
|
||||
KotlinStub$FUN[fqName=test.isNotString, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=true, mayHaveContract=true, name=isNotString]
|
||||
effect:Returns(NOT_NULL) -> param(0) !is KotlinClassTypeBean(classId=kotlin/String, arguments=[], nullable=false)
|
||||
KotlinStub$MODIFIER_LIST[public]
|
||||
KotlinStub$VALUE_PARAMETER_LIST
|
||||
KotlinStub$VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=foo]
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$NULLABLE_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin]
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=Any]
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$NULLABLE_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin]
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=String]
|
||||
KotlinStub$FUN[fqName=test.isNull, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=true, mayHaveContract=true, name=isNull]
|
||||
effect:Returns(TRUE) -> param(0) != null
|
||||
KotlinStub$MODIFIER_LIST[public]
|
||||
KotlinStub$VALUE_PARAMETER_LIST
|
||||
KotlinStub$VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=obj]
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$NULLABLE_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin]
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=Any]
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin]
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=Boolean]
|
||||
KotlinStub$FUN[fqName=test.isString, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=true, mayHaveContract=true, name=isString]
|
||||
effect:Returns(NOT_NULL) -> param(0) is KotlinClassTypeBean(classId=kotlin/String, arguments=[], nullable=false)
|
||||
KotlinStub$MODIFIER_LIST[public]
|
||||
KotlinStub$VALUE_PARAMETER_LIST
|
||||
KotlinStub$VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=foo]
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$NULLABLE_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin]
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=Any]
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$NULLABLE_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin]
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=String]
|
||||
KotlinStub$FUN[fqName=test.isStringCheck, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=true, mayHaveContract=true, name=isStringCheck]
|
||||
effect:Returns(TRUE) -> param(0) is KotlinClassTypeBean(classId=kotlin/Comparable, arguments=[KotlinTypeArgumentBean(projectionKind=STAR, type=null)], nullable=false) || param(0) is KotlinClassTypeBean(classId=kotlin/CharSequence, arguments=[], nullable=false)
|
||||
KotlinStub$MODIFIER_LIST[public]
|
||||
KotlinStub$VALUE_PARAMETER_LIST
|
||||
KotlinStub$VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=x]
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$NULLABLE_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin]
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=Any]
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$NULLABLE_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin]
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=Any]
|
||||
KotlinStub$FUN[fqName=test.isStringOrNumber, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=true, mayHaveContract=true, name=isStringOrNumber]
|
||||
effect:Returns(TRUE) -> param(0) is KotlinClassTypeBean(classId=kotlin/Comparable, arguments=[KotlinTypeArgumentBean(projectionKind=STAR, type=null)], nullable=false) && param(0) is KotlinClassTypeBean(classId=kotlin/CharSequence, arguments=[], nullable=false) || param(0) is KotlinClassTypeBean(classId=kotlin/Number, arguments=[], nullable=false)
|
||||
KotlinStub$MODIFIER_LIST[public]
|
||||
KotlinStub$VALUE_PARAMETER_LIST
|
||||
KotlinStub$VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=x]
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$NULLABLE_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin]
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=Any]
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$NULLABLE_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin]
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=Any]
|
||||
KotlinStub$FUN[fqName=test.myRequire, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=true, mayHaveContract=true, name=myRequire]
|
||||
effect:Returns(WILDCARD) -> param(0)
|
||||
KotlinStub$MODIFIER_LIST[public]
|
||||
KotlinStub$VALUE_PARAMETER_LIST
|
||||
KotlinStub$VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=x]
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin]
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=Boolean]
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin]
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=Unit]
|
||||
KotlinStub$FUN[fqName=test.asSafe, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=true, isTopLevel=true, mayHaveContract=true, name=asSafe]
|
||||
effect:Returns(NOT_NULL) -> param(-1) != null
|
||||
KotlinStub$MODIFIER_LIST[public]
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$NULLABLE_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin]
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=String]
|
||||
KotlinStub$VALUE_PARAMETER_LIST
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$NULLABLE_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin]
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=String]
|
||||
KotlinStub$FUN[fqName=test.test0, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=true, isExtension=true, isTopLevel=true, mayHaveContract=true, name=test0]
|
||||
effect:Returns(TRUE) -> param(-1) is KotlinTypeParameterTypeBean(typeParameterName=T, nullable=false, definitelyNotNull=false)
|
||||
KotlinStub$MODIFIER_LIST[public inline]
|
||||
KotlinStub$TYPE_PARAMETER_LIST
|
||||
KotlinStub$TYPE_PARAMETER[fqName=null, isInVariance=false, isOutVariance=false, name=T]
|
||||
KotlinStub$MODIFIER_LIST[reified]
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin]
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=Number]
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$NULLABLE_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=T]
|
||||
KotlinStub$VALUE_PARAMETER_LIST
|
||||
KotlinStub$TYPE_REFERENCE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$USER_TYPE
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin]
|
||||
KotlinStub$REFERENCE_EXPRESSION[referencedName=Boolean]
|
||||
+66
-5
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.analysis.decompiler.stub.files
|
||||
import com.intellij.psi.stubs.StubElement
|
||||
import com.intellij.util.indexing.FileContentImpl
|
||||
import org.jetbrains.kotlin.analysis.decompiler.stub.file.KotlinClsStubBuilder
|
||||
import org.jetbrains.kotlin.contracts.description.*
|
||||
import org.jetbrains.kotlin.psi.KtProjectionKind
|
||||
import org.jetbrains.kotlin.psi.stubs.impl.*
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
@@ -25,11 +26,22 @@ abstract class AbstractAdditionalStubInfoTest : AbstractDecompiledClassTest() {
|
||||
|
||||
private fun extractAdditionInfo(stub: StubElement<*>, builder: StringBuilder, level: Int) {
|
||||
builder.append(stub.toString())
|
||||
if (stub is KotlinUserTypeStubImpl) {
|
||||
val upperBound = stub.upperBound
|
||||
if (upperBound != null) {
|
||||
builder.append(" ft: ")
|
||||
appendFlexibleTypeInfo(builder, upperBound)
|
||||
when (stub) {
|
||||
is KotlinUserTypeStubImpl -> {
|
||||
val upperBound = stub.upperBound
|
||||
if (upperBound != null) {
|
||||
builder.append(" ft: ")
|
||||
appendFlexibleTypeInfo(builder, upperBound)
|
||||
}
|
||||
}
|
||||
is KotlinFunctionStubImpl -> {
|
||||
val contract = stub.contract
|
||||
if (contract != null) {
|
||||
for (element in contract) {
|
||||
builder.append("\n" + " ".repeat(level)).append("effect:")
|
||||
element.accept(KotlinContractRenderer(builder), null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (child in stub.childrenStubs) {
|
||||
@@ -77,4 +89,53 @@ abstract class AbstractAdditionalStubInfoTest : AbstractDecompiledClassTest() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinContractRenderer(private val buffer: StringBuilder) : KtContractDescriptionVisitor<Unit, Nothing?, KotlinTypeBean, Nothing?>() {
|
||||
override fun visitConditionalEffectDeclaration(conditionalEffect: KtConditionalEffectDeclaration<KotlinTypeBean, Nothing?>, data: Nothing?) {
|
||||
conditionalEffect.effect.accept(this, data)
|
||||
buffer.append(" -> ")
|
||||
conditionalEffect.condition.accept(this, data)
|
||||
}
|
||||
|
||||
override fun visitReturnsEffectDeclaration(returnsEffect: KtReturnsEffectDeclaration<KotlinTypeBean, Nothing?>, data: Nothing?) {
|
||||
buffer.append("Returns(")
|
||||
returnsEffect.value.accept(this, data)
|
||||
buffer.append(")")
|
||||
}
|
||||
|
||||
override fun visitCallsEffectDeclaration(callsEffect: KtCallsEffectDeclaration<KotlinTypeBean, Nothing?>, data: Nothing?) {
|
||||
buffer.append("CallsInPlace(")
|
||||
callsEffect.valueParameterReference.accept(this, data)
|
||||
buffer.append(", ${callsEffect.kind})")
|
||||
}
|
||||
|
||||
override fun visitLogicalBinaryOperationContractExpression(binaryLogicExpression: KtBinaryLogicExpression<KotlinTypeBean, Nothing?>, data: Nothing?) {
|
||||
binaryLogicExpression.left.accept(this, data)
|
||||
buffer.append(" ${binaryLogicExpression.kind.token} ")
|
||||
binaryLogicExpression.right.accept(this, data)
|
||||
}
|
||||
|
||||
override fun visitLogicalNot(logicalNot: KtLogicalNot<KotlinTypeBean, Nothing?>, data: Nothing?) {
|
||||
logicalNot.arg.accept(this, data)
|
||||
}
|
||||
|
||||
override fun visitIsInstancePredicate(isInstancePredicate: KtIsInstancePredicate<KotlinTypeBean, Nothing?>, data: Nothing?) {
|
||||
isInstancePredicate.arg.accept(this, data)
|
||||
buffer.append(" ${if (isInstancePredicate.isNegated) "!" else ""}is ${isInstancePredicate.type}")
|
||||
}
|
||||
|
||||
override fun visitIsNullPredicate(isNullPredicate: KtIsNullPredicate<KotlinTypeBean, Nothing?>, data: Nothing?) {
|
||||
isNullPredicate.arg.accept(this, data)
|
||||
buffer.append(" ${if (isNullPredicate.isNegated) "!=" else "=="} null")
|
||||
}
|
||||
|
||||
override fun visitConstantDescriptor(constantReference: KtConstantReference<KotlinTypeBean, Nothing?>, data: Nothing?) {
|
||||
buffer.append(constantReference.name)
|
||||
}
|
||||
|
||||
override fun visitValueParameterReference(valueParameterReference: KtValueParameterReference<KotlinTypeBean, Nothing?>, data: Nothing?) {
|
||||
buffer.append("param(").append(valueParameterReference.parameterIndex).append(")")
|
||||
}
|
||||
|
||||
}
|
||||
+6
@@ -30,6 +30,12 @@ public class AdditionalStubInfoTestGenerated extends AbstractAdditionalStubInfoT
|
||||
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/AnnotatedFlexibleTypes/");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("Contracts")
|
||||
public void testContracts() throws Exception {
|
||||
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/Contracts/");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("OuterClassesWithFlexibleArgs")
|
||||
public void testOuterClassesWithFlexibleArgs() throws Exception {
|
||||
|
||||
+6
-1
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.resolve.DataClassResolver
|
||||
import org.jetbrains.kotlin.serialization.deserialization.AnnotatedCallableKind
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||
|
||||
fun createPackageDeclarationsStubs(
|
||||
parentStub: StubElement<out PsiElement>,
|
||||
@@ -173,6 +174,7 @@ private class FunctionClsStubBuilder(
|
||||
// Note that arguments passed to stubs here and elsewhere are based on what stabs would be generated based on decompiled code
|
||||
// As functions are never decompiled to fun f() = 1 form, hasBlockBody is always true
|
||||
// This info is anyway irrelevant for the purposes these stubs are used
|
||||
val hasContract = functionProto.hasContract()
|
||||
return KotlinFunctionStubImpl(
|
||||
parent,
|
||||
callableName.ref(),
|
||||
@@ -182,7 +184,10 @@ private class FunctionClsStubBuilder(
|
||||
hasBlockBody = true,
|
||||
hasBody = Flags.MODALITY.get(functionProto.flags) != Modality.ABSTRACT,
|
||||
hasTypeParameterListBeforeFunctionName = functionProto.typeParameterList.isNotEmpty(),
|
||||
mayHaveContract = functionProto.hasContract()
|
||||
mayHaveContract = hasContract,
|
||||
runIf(hasContract) {
|
||||
ClsContractBuilder(c, typeStubBuilder).loadContract(functionProto)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.analysis.decompiler.stub
|
||||
|
||||
import org.jetbrains.kotlin.contracts.description.KtBooleanValueParameterReference
|
||||
import org.jetbrains.kotlin.contracts.description.KtConstantReference
|
||||
import org.jetbrains.kotlin.contracts.description.KtEffectDeclaration
|
||||
import org.jetbrains.kotlin.contracts.description.KtValueParameterReference
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.isInstanceType
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.psi.stubs.impl.*
|
||||
import org.jetbrains.kotlin.psi.stubs.impl.KotlinContractEffectType.Companion.IGNORE_REFERENCE_PARAMETER_NAME
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoBufContractDeserializer
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getClassId
|
||||
|
||||
class ClsContractBuilder(private val c: ClsStubBuilderContext, private val typeStubBuilder: TypeClsStubBuilder) :
|
||||
ProtoBufContractDeserializer<KotlinTypeBean, Nothing?, ProtoBuf.Function>() {
|
||||
|
||||
fun loadContract(proto: ProtoBuf.Function): List<KtEffectDeclaration<KotlinTypeBean, Nothing?>>? {
|
||||
return proto.contract.effectList.map { loadPossiblyConditionalEffect(it, proto) ?: return null }
|
||||
}
|
||||
|
||||
override fun extractVariable(valueParameterIndex: Int, owner: ProtoBuf.Function): KtValueParameterReference<KotlinTypeBean, Nothing?> {
|
||||
val type = if (valueParameterIndex < 0) {
|
||||
owner.receiverType
|
||||
} else owner.valueParameterList[valueParameterIndex].type
|
||||
return if (type.hasClassName() && c.nameResolver.getClassId(type.className) == StandardClassIds.Boolean) {
|
||||
KtBooleanValueParameterReference(valueParameterIndex, name = IGNORE_REFERENCE_PARAMETER_NAME)
|
||||
} else KtValueParameterReference(valueParameterIndex, name = IGNORE_REFERENCE_PARAMETER_NAME)
|
||||
}
|
||||
|
||||
override fun extractType(proto: ProtoBuf.Expression): KotlinTypeBean? {
|
||||
return typeStubBuilder.createKotlinTypeBean(proto.isInstanceType(c.typeTable))
|
||||
}
|
||||
|
||||
override fun loadConstant(value: ProtoBuf.Expression.ConstantValue): KtConstantReference<KotlinTypeBean, Nothing?> {
|
||||
return when (value) {
|
||||
ProtoBuf.Expression.ConstantValue.TRUE -> KotlinContractConstantValues.TRUE
|
||||
ProtoBuf.Expression.ConstantValue.FALSE -> KotlinContractConstantValues.FALSE
|
||||
ProtoBuf.Expression.ConstantValue.NULL -> KotlinContractConstantValues.NULL
|
||||
}
|
||||
}
|
||||
|
||||
override fun getNotNull(): KtConstantReference<KotlinTypeBean, Nothing?> {
|
||||
return KotlinContractConstantValues.NOT_NULL
|
||||
}
|
||||
|
||||
override fun getWildcard(): KtConstantReference<KotlinTypeBean, Nothing?> {
|
||||
return KotlinContractConstantValues.WILDCARD
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -150,7 +150,7 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun createKotlinTypeBean(
|
||||
fun createKotlinTypeBean(
|
||||
type: Type?
|
||||
): KotlinTypeBean? {
|
||||
if (type == null) return null
|
||||
|
||||
Reference in New Issue
Block a user