Introduce 'mayHaveContract'-flag in stubs

This is needed for further commit, which supports contracts-based
smartcasts in partial body resolve mode.

NB: Stubs can be built from 3 sources:
- source code (contract presence can be checked by PSI)
- binary data (contract presence can be checked by Kotlin Metadata)
- decompiled sources

The last case is a bit of a headache, because usually bodies are omitted
in decompiled sources. To workaround it, we have to inject stubbed
contract-call in the body.
This commit is contained in:
Dmitry Savvinov
2018-07-27 11:18:13 +03:00
parent 24245c2245
commit 5ab79a111d
59 changed files with 235 additions and 127 deletions
@@ -20,6 +20,7 @@ import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.contracts.ContractDeserializerImpl
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.NotFoundClasses
import org.jetbrains.kotlin.idea.caches.IDEKotlinBinaryClassCache
@@ -63,11 +64,16 @@ class DeserializerForClassfileDecompiler(
val annotationAndConstantLoader =
BinaryClassAnnotationAndConstantLoaderImpl(moduleDescriptor, notFoundClasses, storageManager, classFinder)
val configuration = object : DeserializationConfiguration {
override val readDeserializedContracts: Boolean
get() = true
}
deserializationComponents = DeserializationComponents(
storageManager, moduleDescriptor, DeserializationConfiguration.Default, classDataFinder, annotationAndConstantLoader,
storageManager, moduleDescriptor, configuration, classDataFinder, annotationAndConstantLoader,
packageFragmentProvider, ResolveEverythingToKotlinAnyLocalClassifierResolver(builtIns), LoggingErrorReporter(LOG),
LookupTracker.DO_NOTHING, JavaFlexibleTypeDeserializer, emptyList(), notFoundClasses,
ContractDeserializer.DEFAULT,
ContractDeserializerImpl(configuration),
extensionRegistryLite = JvmProtoBufUtil.EXTENSION_REGISTRY
)
}
@@ -180,7 +180,8 @@ private class FunctionClsStubBuilder(
isExtension = functionProto.hasReceiver(),
hasBlockBody = true,
hasBody = Flags.MODALITY.get(functionProto.flags) != Modality.ABSTRACT,
hasTypeParameterListBeforeFunctionName = functionProto.typeParameterList.isNotEmpty()
hasTypeParameterListBeforeFunctionName = functionProto.typeParameterList.isNotEmpty(),
hasContract = functionProto.hasContract()
)
}
}
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.idea.decompiler.textBuilder
import com.intellij.openapi.util.TextRange
import org.jetbrains.kotlin.contracts.description.ContractProviderKey
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.decompiler.navigation.ByDescriptorIndexer
import org.jetbrains.kotlin.name.FqName
@@ -31,6 +32,7 @@ import org.jetbrains.kotlin.types.isFlexible
private val DECOMPILED_CODE_COMMENT = "/* compiled code */"
private val DECOMPILED_COMMENT_FOR_PARAMETER = "/* = compiled code */"
private val FLEXIBLE_TYPE_COMMENT = "/* platform type */"
private val DECOMPILED_CONTRACT_STUB = "contract { /* compiled contract */ }"
fun DescriptorRendererOptions.defaultDecompilerRendererOptions() {
withDefinedIn = false
@@ -89,7 +91,13 @@ fun buildDecompiledText(
if (descriptor is FunctionDescriptor || descriptor is PropertyDescriptor) {
if ((descriptor as MemberDescriptor).modality != Modality.ABSTRACT) {
if (descriptor is FunctionDescriptor) {
builder.append(" { ").append(DECOMPILED_CODE_COMMENT).append(" }")
with(builder) {
append(" { ")
if (descriptor.getUserData(ContractProviderKey)?.getContractDescription() != null) {
append(DECOMPILED_CONTRACT_STUB).append("; ")
}
append(DECOMPILED_CODE_COMMENT).append(" }")
}
}
else {
// descriptor instanceof PropertyDescriptor
@@ -156,6 +156,10 @@ public class IdeStubIndexService extends StubIndexService {
if (TypeIndexUtilKt.isProbablyNothing(stub.getPsi().getTypeReference())) {
sink.occurrence(KotlinProbablyNothingFunctionShortNameIndex.getInstance().getKey(), name);
}
if (stub.mayHaveContract()) {
sink.occurrence(KotlinProbablyContractedFunctionShortNameIndex.getInstance().getKey(), name);
}
}
if (stub.isTopLevel()) {