[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:
@@ -23,12 +23,12 @@ object KotlinStubVersions {
|
||||
// Though only kotlin declarations (no code in the bodies) are stubbed, please do increase this version
|
||||
// if you are not 100% sure it can be avoided.
|
||||
// Increasing this version will lead to reindexing of all kotlin source files on the first IDE startup with the new version.
|
||||
const val SOURCE_STUB_VERSION = 149
|
||||
const val SOURCE_STUB_VERSION = 150
|
||||
|
||||
// Binary stub version should be increased if stub format (org.jetbrains.kotlin.psi.stubs.impl) is changed
|
||||
// or changes are made to the core stub building code (org.jetbrains.kotlin.idea.decompiler.stubBuilder).
|
||||
// Increasing this version will lead to reindexing of all binary files that are potentially kotlin binaries (including all class files).
|
||||
private const val BINARY_STUB_VERSION = 85
|
||||
private const val BINARY_STUB_VERSION = 86
|
||||
|
||||
// Classfile stub version should be increased if changes are made to classfile stub building subsystem (org.jetbrains.kotlin.idea.decompiler.classFile)
|
||||
// Increasing this version will lead to reindexing of all classfiles.
|
||||
|
||||
@@ -51,7 +51,8 @@ public class KtFunctionElementType extends KtStubElementType<KotlinFunctionStub,
|
||||
return new KotlinFunctionStubImpl(
|
||||
(StubElement<?>) parentStub, StringRef.fromString(psi.getName()), isTopLevel, fqName,
|
||||
isExtension, hasBlockBody, hasBody, psi.hasTypeParameterListBeforeFunctionName(),
|
||||
psi.mayHaveContract()
|
||||
psi.mayHaveContract(),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
@@ -67,7 +68,11 @@ public class KtFunctionElementType extends KtStubElementType<KotlinFunctionStub,
|
||||
dataStream.writeBoolean(stub.hasBlockBody());
|
||||
dataStream.writeBoolean(stub.hasBody());
|
||||
dataStream.writeBoolean(stub.hasTypeParameterListBeforeFunctionName());
|
||||
dataStream.writeBoolean(stub.mayHaveContract());
|
||||
boolean haveContract = stub.mayHaveContract();
|
||||
dataStream.writeBoolean(haveContract);
|
||||
if (haveContract && stub instanceof KotlinFunctionStubImpl) {
|
||||
((KotlinFunctionStubImpl) stub).serializeContract(dataStream);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -84,10 +89,9 @@ public class KtFunctionElementType extends KtStubElementType<KotlinFunctionStub,
|
||||
boolean hasBody = dataStream.readBoolean();
|
||||
boolean hasTypeParameterListBeforeFunctionName = dataStream.readBoolean();
|
||||
boolean mayHaveContract = dataStream.readBoolean();
|
||||
|
||||
return new KotlinFunctionStubImpl(
|
||||
(StubElement<?>) parentStub, name, isTopLevel, fqName, isExtension, hasBlockBody, hasBody,
|
||||
hasTypeParameterListBeforeFunctionName, mayHaveContract
|
||||
hasTypeParameterListBeforeFunctionName, mayHaveContract, mayHaveContract ? KotlinFunctionStubImpl.Companion.deserializeContract(dataStream) : null
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ public class KtUserTypeElementType extends KtStubElementType<KotlinUserTypeStub,
|
||||
}
|
||||
}
|
||||
|
||||
private static void serializeType(@NotNull StubOutputStream dataStream, @Nullable KotlinTypeBean type) throws IOException {
|
||||
public static void serializeType(@NotNull StubOutputStream dataStream, @Nullable KotlinTypeBean type) throws IOException {
|
||||
dataStream.writeInt(KotlinTypeBeanKind.fromBean(type).ordinal());
|
||||
if (type instanceof KotlinClassTypeBean) {
|
||||
StubUtils.serializeClassId(dataStream, ((KotlinClassTypeBean) type).getClassId());
|
||||
@@ -94,7 +94,7 @@ public class KtUserTypeElementType extends KtStubElementType<KotlinUserTypeStub,
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static KotlinTypeBean deserializeType(@NotNull StubInputStream dataStream) throws IOException {
|
||||
public static KotlinTypeBean deserializeType(@NotNull StubInputStream dataStream) throws IOException {
|
||||
KotlinTypeBeanKind typeKind = KotlinTypeBeanKind.values()[dataStream.readInt()];
|
||||
switch (typeKind) {
|
||||
case CLASS: {
|
||||
|
||||
+154
-1
@@ -7,12 +7,165 @@ package org.jetbrains.kotlin.psi.stubs.impl
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.stubs.StubElement
|
||||
import com.intellij.psi.stubs.StubInputStream
|
||||
import com.intellij.psi.stubs.StubOutputStream
|
||||
import org.jetbrains.kotlin.contracts.description.*
|
||||
import org.jetbrains.kotlin.psi.KtContractEffect
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinContractEffectStub
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtContractEffectElementType
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtUserTypeElementType.deserializeType
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtUserTypeElementType.serializeType
|
||||
|
||||
class KotlinContractEffectStubImpl(
|
||||
parent: StubElement<out PsiElement>?,
|
||||
elementType: KtContractEffectElementType
|
||||
) : KotlinPlaceHolderStubImpl<KtContractEffect>(parent, elementType), KotlinContractEffectStub {
|
||||
) : KotlinPlaceHolderStubImpl<KtContractEffect>(parent, elementType), KotlinContractEffectStub
|
||||
|
||||
enum class KotlinContractEffectType {
|
||||
CALLS {
|
||||
override fun deserialize(dataStream: StubInputStream): KtCallsEffectDeclaration<KotlinTypeBean, Nothing?> {
|
||||
val declaration = PARAMETER_REFERENCE.deserialize(dataStream)
|
||||
val range = EventOccurrencesRange.values()[dataStream.readInt()]
|
||||
return KtCallsEffectDeclaration(declaration as KtValueParameterReference, range)
|
||||
}
|
||||
},
|
||||
RETURNS {
|
||||
override fun deserialize(dataStream: StubInputStream): KtContractDescriptionElement<KotlinTypeBean, Nothing?> {
|
||||
return KtReturnsEffectDeclaration(CONSTANT.deserialize(dataStream) as KtConstantReference)
|
||||
}
|
||||
},
|
||||
CONDITIONAL {
|
||||
override fun deserialize(dataStream: StubInputStream): KtContractDescriptionElement<KotlinTypeBean, Nothing?> {
|
||||
val descriptionElement = values()[dataStream.readInt()].deserialize(dataStream)
|
||||
val condition = values()[dataStream.readInt()].deserialize(dataStream)
|
||||
return KtConditionalEffectDeclaration(
|
||||
descriptionElement as KtEffectDeclaration,
|
||||
condition as KtBooleanExpression
|
||||
)
|
||||
}
|
||||
},
|
||||
IS_NULL {
|
||||
override fun deserialize(dataStream: StubInputStream): KtContractDescriptionElement<KotlinTypeBean, Nothing?> {
|
||||
return KtIsNullPredicate(
|
||||
PARAMETER_REFERENCE.deserialize(dataStream) as KtValueParameterReference,
|
||||
dataStream.readBoolean()
|
||||
)
|
||||
}
|
||||
},
|
||||
IS_INSTANCE {
|
||||
override fun deserialize(dataStream: StubInputStream): KtContractDescriptionElement<KotlinTypeBean, Nothing?> {
|
||||
return KtIsInstancePredicate(
|
||||
PARAMETER_REFERENCE.deserialize(dataStream) as KtValueParameterReference,
|
||||
deserializeType(dataStream)!!,
|
||||
dataStream.readBoolean()
|
||||
)
|
||||
}
|
||||
},
|
||||
NOT {
|
||||
override fun deserialize(dataStream: StubInputStream): KtContractDescriptionElement<KotlinTypeBean, Nothing?> {
|
||||
return KtLogicalNot(values()[dataStream.readInt()].deserialize(dataStream) as KtBooleanExpression)
|
||||
}
|
||||
},
|
||||
BOOLEAN_LOGIC {
|
||||
override fun deserialize(dataStream: StubInputStream): KtContractDescriptionElement<KotlinTypeBean, Nothing?> {
|
||||
val kind = if (dataStream.readBoolean()) LogicOperationKind.AND else LogicOperationKind.OR
|
||||
val left = values()[dataStream.readInt()].deserialize(dataStream) as KtBooleanExpression
|
||||
val right = values()[dataStream.readInt()].deserialize(dataStream) as KtBooleanExpression
|
||||
return KtBinaryLogicExpression(left, right, kind)
|
||||
}
|
||||
},
|
||||
PARAMETER_REFERENCE {
|
||||
override fun deserialize(dataStream: StubInputStream): KtValueParameterReference<KotlinTypeBean, Nothing?> {
|
||||
return KtValueParameterReference(dataStream.readInt(), IGNORE_REFERENCE_PARAMETER_NAME)
|
||||
}
|
||||
},
|
||||
CONSTANT {
|
||||
override fun deserialize(dataStream: StubInputStream): KtContractDescriptionElement<KotlinTypeBean, Nothing?> {
|
||||
return when (val str = dataStream.readNameString()!!) {
|
||||
"TRUE" -> KotlinContractConstantValues.TRUE
|
||||
"FALSE" -> KotlinContractConstantValues.FALSE
|
||||
"NULL" -> KotlinContractConstantValues.NULL
|
||||
"NOT_NULL" -> KotlinContractConstantValues.NOT_NULL
|
||||
"WILDCARD" -> KotlinContractConstantValues.WILDCARD
|
||||
else -> error("Unexpected $str")
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
abstract fun deserialize(dataStream: StubInputStream): KtContractDescriptionElement<KotlinTypeBean, Nothing?>
|
||||
|
||||
companion object {
|
||||
const val IGNORE_REFERENCE_PARAMETER_NAME = "<ignore>"
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinContractSerializationVisitor(val dataStream: StubOutputStream) :
|
||||
KtContractDescriptionVisitor<Unit, Nothing?, KotlinTypeBean, Nothing?>() {
|
||||
override fun visitConditionalEffectDeclaration(
|
||||
conditionalEffect: KtConditionalEffectDeclaration<KotlinTypeBean, Nothing?>,
|
||||
data: Nothing?
|
||||
) {
|
||||
dataStream.writeInt(KotlinContractEffectType.CONDITIONAL.ordinal)
|
||||
conditionalEffect.effect.accept(this, data)
|
||||
conditionalEffect.condition.accept(this, data)
|
||||
}
|
||||
|
||||
override fun visitReturnsEffectDeclaration(returnsEffect: KtReturnsEffectDeclaration<KotlinTypeBean, Nothing?>, data: Nothing?) {
|
||||
dataStream.writeInt(KotlinContractEffectType.RETURNS.ordinal)
|
||||
returnsEffect.value.accept(this, data)
|
||||
}
|
||||
|
||||
override fun visitCallsEffectDeclaration(callsEffect: KtCallsEffectDeclaration<KotlinTypeBean, Nothing?>, data: Nothing?) {
|
||||
dataStream.writeInt(KotlinContractEffectType.CALLS.ordinal)
|
||||
callsEffect.valueParameterReference.accept(this, data)
|
||||
dataStream.writeInt(callsEffect.kind.ordinal)
|
||||
}
|
||||
|
||||
override fun visitLogicalBinaryOperationContractExpression(
|
||||
binaryLogicExpression: KtBinaryLogicExpression<KotlinTypeBean, Nothing?>,
|
||||
data: Nothing?
|
||||
) {
|
||||
dataStream.writeInt(KotlinContractEffectType.BOOLEAN_LOGIC.ordinal)
|
||||
dataStream.writeBoolean(binaryLogicExpression.kind == LogicOperationKind.AND)
|
||||
binaryLogicExpression.left.accept(this, data)
|
||||
binaryLogicExpression.right.accept(this, data)
|
||||
}
|
||||
|
||||
override fun visitLogicalNot(logicalNot: KtLogicalNot<KotlinTypeBean, Nothing?>, data: Nothing?) {
|
||||
dataStream.writeInt(KotlinContractEffectType.NOT.ordinal)
|
||||
logicalNot.arg.accept(this, data)
|
||||
}
|
||||
|
||||
override fun visitIsInstancePredicate(isInstancePredicate: KtIsInstancePredicate<KotlinTypeBean, Nothing?>, data: Nothing?) {
|
||||
dataStream.writeInt(KotlinContractEffectType.IS_INSTANCE.ordinal)
|
||||
isInstancePredicate.arg.accept(this, data)
|
||||
serializeType(dataStream, isInstancePredicate.type)
|
||||
dataStream.writeBoolean(isInstancePredicate.isNegated)
|
||||
}
|
||||
|
||||
override fun visitIsNullPredicate(isNullPredicate: KtIsNullPredicate<KotlinTypeBean, Nothing?>, data: Nothing?) {
|
||||
dataStream.writeInt(KotlinContractEffectType.IS_NULL.ordinal)
|
||||
isNullPredicate.arg.accept(this, data)
|
||||
dataStream.writeBoolean(isNullPredicate.isNegated)
|
||||
}
|
||||
|
||||
|
||||
override fun visitConstantDescriptor(constantReference: KtConstantReference<KotlinTypeBean, Nothing?>, data: Nothing?) {
|
||||
dataStream.writeInt(KotlinContractEffectType.CONSTANT.ordinal)
|
||||
dataStream.writeName(constantReference.name)
|
||||
}
|
||||
|
||||
override fun visitValueParameterReference(valueParameterReference: KtValueParameterReference<KotlinTypeBean, Nothing?>, data: Nothing?) {
|
||||
dataStream.writeInt(KotlinContractEffectType.PARAMETER_REFERENCE.ordinal)
|
||||
dataStream.writeInt(valueParameterReference.parameterIndex)
|
||||
}
|
||||
}
|
||||
|
||||
object KotlinContractConstantValues {
|
||||
val NULL = KtConstantReference<KotlinTypeBean, Nothing?>("NULL")
|
||||
val WILDCARD = KtConstantReference<KotlinTypeBean, Nothing?>("WILDCARD")
|
||||
val NOT_NULL = KtConstantReference<KotlinTypeBean, Nothing?>("NOT_NULL")
|
||||
|
||||
val TRUE = KtBooleanConstantReference<KotlinTypeBean, Nothing?>("TRUE")
|
||||
val FALSE = KtBooleanConstantReference<KotlinTypeBean, Nothing?>("FALSE")
|
||||
}
|
||||
@@ -16,13 +16,17 @@
|
||||
|
||||
package org.jetbrains.kotlin.psi.stubs.impl
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.stubs.StubElement
|
||||
import com.intellij.psi.stubs.StubInputStream
|
||||
import com.intellij.psi.stubs.StubOutputStream
|
||||
import com.intellij.util.io.StringRef
|
||||
import org.jetbrains.kotlin.contracts.description.KtContractDescriptionElement
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinFunctionStub
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import com.intellij.psi.PsiElement
|
||||
import java.io.IOException
|
||||
|
||||
class KotlinFunctionStubImpl(
|
||||
parent: StubElement<out PsiElement>?,
|
||||
@@ -33,7 +37,8 @@ class KotlinFunctionStubImpl(
|
||||
private val hasBlockBody: Boolean,
|
||||
private val hasBody: Boolean,
|
||||
private val hasTypeParameterListBeforeFunctionName: Boolean,
|
||||
private val mayHaveContract: Boolean
|
||||
private val mayHaveContract: Boolean,
|
||||
val contract: List<KtContractDescriptionElement<KotlinTypeBean, Nothing?>>?
|
||||
) : KotlinStubBaseImpl<KtNamedFunction>(parent, KtStubElementTypes.FUNCTION), KotlinFunctionStub {
|
||||
init {
|
||||
if (isTopLevel && fqName == null) {
|
||||
@@ -50,4 +55,24 @@ class KotlinFunctionStubImpl(
|
||||
override fun hasBody() = hasBody
|
||||
override fun hasTypeParameterListBeforeFunctionName() = hasTypeParameterListBeforeFunctionName
|
||||
override fun mayHaveContract(): Boolean = mayHaveContract
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun serializeContract(dataStream: StubOutputStream) {
|
||||
val effects: List<KtContractDescriptionElement<KotlinTypeBean, Nothing?>>? = contract
|
||||
dataStream.writeInt(effects?.size ?: 0)
|
||||
val visitor = KotlinContractSerializationVisitor(dataStream)
|
||||
effects?.forEach { it.accept(visitor, null) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun deserializeContract(dataStream: StubInputStream): List<KtContractDescriptionElement<KotlinTypeBean, Nothing?>> {
|
||||
val effects = mutableListOf<KtContractDescriptionElement<KotlinTypeBean, Nothing?>>()
|
||||
val count: Int = dataStream.readInt()
|
||||
for (i in 0 until count) {
|
||||
val effectType: KotlinContractEffectType = KotlinContractEffectType.values()[dataStream.readInt()]
|
||||
effects.add(effectType.deserialize(dataStream))
|
||||
}
|
||||
return effects
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user