[stubs] fix cls stubs for declarations with context receivers

^KTIJ-21243 fixed
This commit is contained in:
Ilya Kirillov
2022-06-16 17:13:03 +02:00
parent a47880a98b
commit ba797fa1b4
12 changed files with 297 additions and 12 deletions
@@ -0,0 +1,24 @@
// !LANGUAGE: +ContextReceivers
private open class ContextReceiversCallableMembers {
context(A, B)
private fun Int.function(): Int = valueA + valueB
context(A, B)
private val Int.property: Int get() = valueA + valueB
context(A, B)
private var Int.propertyWithSetter: Int
get() = valueA + valueB
set(v) { println(valueA + valueB) }
}
class A {
val valueA: Int = 10
}
class B {
val valueB: Int = 11
}
@@ -0,0 +1,73 @@
PsiJetFileStubImpl[package=]
PACKAGE_DIRECTIVE
IMPORT_LIST
CLASS[classId=/ContextReceiversCallableMembers, fqName=ContextReceiversCallableMembers, isEnumEntry=false, isInterface=false, isLocal=false, isTopLevel=true, name=ContextReceiversCallableMembers, superNames=[]]
MODIFIER_LIST[open private]
PRIMARY_CONSTRUCTOR
MODIFIER_LIST[public]
VALUE_PARAMETER_LIST
CLASS_BODY
PROPERTY[fqName=ContextReceiversCallableMembers.property, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=true, isTopLevel=false, isVar=false, name=property]
CONTEXT_RECEIVER_LIST
CONTEXT_RECEIVER
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=A]
CONTEXT_RECEIVER
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=B]
MODIFIER_LIST[private final]
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Int]
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Int]
PROPERTY[fqName=ContextReceiversCallableMembers.propertyWithSetter, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=true, isTopLevel=false, isVar=true, name=propertyWithSetter]
CONTEXT_RECEIVER_LIST
CONTEXT_RECEIVER
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=A]
CONTEXT_RECEIVER
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=B]
MODIFIER_LIST[private final]
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Int]
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Int]
FUN[fqName=ContextReceiversCallableMembers.function, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=true, isTopLevel=false, mayHaveContract=false, name=function]
CONTEXT_RECEIVER_LIST
CONTEXT_RECEIVER
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=A]
CONTEXT_RECEIVER
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=B]
MODIFIER_LIST[private final]
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Int]
VALUE_PARAMETER_LIST
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Int]
@@ -0,0 +1,14 @@
// !LANGUAGE: +ContextReceivers
context(A, B)
private open class ContextReceiversOnClass {
}
class A {
val valueA: Int = 10
}
class B {
val valueB: Int = 11
}
@@ -0,0 +1,18 @@
PsiJetFileStubImpl[package=]
PACKAGE_DIRECTIVE
IMPORT_LIST
CLASS[classId=/ContextReceiversOnClass, fqName=ContextReceiversOnClass, isEnumEntry=false, isInterface=false, isLocal=false, isTopLevel=true, name=ContextReceiversOnClass, superNames=[]]
CONTEXT_RECEIVER_LIST
CONTEXT_RECEIVER
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=A]
CONTEXT_RECEIVER
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=B]
MODIFIER_LIST[open private]
PRIMARY_CONSTRUCTOR
MODIFIER_LIST[public]
VALUE_PARAMETER_LIST
CLASS_BODY
@@ -0,0 +1,23 @@
// JVM_FILE_NAME: ContextReceiversOnTopLevelCallablesKt
// !LANGUAGE: +ContextReceivers
context(A, B)
private fun Int.function(): Int = valueA + valueB
context(A, B)
private val Int.property: Int get() = valueA + valueB
context(A, B)
private var Int.propertyWithSetter: Int
get() = valueA + valueB
set(v) { println(valueA + valueB) }
class A {
val valueA: Int = 10
}
class B {
val valueB: Int = 11
}
@@ -0,0 +1,67 @@
PsiJetFileStubImpl[package=]
PACKAGE_DIRECTIVE
IMPORT_LIST
PROPERTY[fqName=property, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=true, isTopLevel=true, isVar=false, name=property]
CONTEXT_RECEIVER_LIST
CONTEXT_RECEIVER
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=A]
CONTEXT_RECEIVER
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=B]
MODIFIER_LIST[private]
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Int]
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Int]
PROPERTY[fqName=propertyWithSetter, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=true, isTopLevel=true, isVar=true, name=propertyWithSetter]
CONTEXT_RECEIVER_LIST
CONTEXT_RECEIVER
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=A]
CONTEXT_RECEIVER
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=B]
MODIFIER_LIST[private]
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Int]
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Int]
FUN[fqName=function, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=true, isTopLevel=true, mayHaveContract=false, name=function]
CONTEXT_RECEIVER_LIST
CONTEXT_RECEIVER
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=A]
CONTEXT_RECEIVER
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=B]
MODIFIER_LIST[private]
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Int]
VALUE_PARAMETER_LIST
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Int]
@@ -96,6 +96,24 @@ public class ClsStubBuilderTestGenerated extends AbstractClsStubBuilderTest {
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/clsFileStubBuilder/Const/");
}
@Test
@TestMetadata("ContextReceiversCallableMembers")
public void testContextReceiversCallableMembers() throws Exception {
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/clsFileStubBuilder/ContextReceiversCallableMembers/");
}
@Test
@TestMetadata("ContextReceiversOnClass")
public void testContextReceiversOnClass() throws Exception {
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/clsFileStubBuilder/ContextReceiversOnClass/");
}
@Test
@TestMetadata("ContextReceiversOnTopLevelCallables")
public void testContextReceiversOnTopLevelCallables() throws Exception {
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/clsFileStubBuilder/ContextReceiversOnTopLevelCallables/");
}
@Test
@TestMetadata("Contracts")
public void testContracts() throws Exception {
@@ -97,9 +97,21 @@ public class ByDecompiledPsiStubBuilderTestGenerated extends AbstractByDecompile
}
@Test
@TestMetadata("ContextReceivers")
public void testContextReceivers() throws Exception {
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/clsFileStubBuilder/ContextReceivers/");
@TestMetadata("ContextReceiversCallableMembers")
public void testContextReceiversCallableMembers() throws Exception {
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/clsFileStubBuilder/ContextReceiversCallableMembers/");
}
@Test
@TestMetadata("ContextReceiversOnClass")
public void testContextReceiversOnClass() throws Exception {
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/clsFileStubBuilder/ContextReceiversOnClass/");
}
@Test
@TestMetadata("ContextReceiversOnTopLevelCallables")
public void testContextReceiversOnTopLevelCallables() throws Exception {
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/clsFileStubBuilder/ContextReceiversOnTopLevelCallables/");
}
@Test
@@ -9,10 +9,7 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.ProtoBuf.MemberKind
import org.jetbrains.kotlin.metadata.ProtoBuf.Modality
import org.jetbrains.kotlin.metadata.deserialization.Flags
import org.jetbrains.kotlin.metadata.deserialization.hasReceiver
import org.jetbrains.kotlin.metadata.deserialization.receiverType
import org.jetbrains.kotlin.metadata.deserialization.returnType
import org.jetbrains.kotlin.metadata.deserialization.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
import org.jetbrains.kotlin.psi.stubs.impl.KotlinFunctionStubImpl
@@ -89,10 +86,12 @@ abstract class CallableClsStubBuilder(
) {
protected val c = outerContext.child(typeParameters)
protected val typeStubBuilder = TypeClsStubBuilder(c)
private val contextReceiversListStubBuilder = ContextReceiversListStubBuilder(c)
protected val isTopLevel: Boolean get() = protoContainer is ProtoContainer.Package
protected val callableStub: StubElement<out PsiElement> by lazy(LazyThreadSafetyMode.NONE) { doCreateCallableStub(parent) }
fun build() {
contextReceiversListStubBuilder.createContextReceiverStubs(callableStub, contextReceiverTypes)
createModifierListStub()
val typeConstraintListData = typeStubBuilder.createTypeParameterListStub(callableStub, typeParameters)
createReceiverTypeReferenceStub()
@@ -105,6 +104,7 @@ abstract class CallableClsStubBuilder(
abstract val receiverAnnotations: List<ClassIdWithTarget>
abstract val returnType: ProtoBuf.Type?
abstract val contextReceiverTypes: List<ProtoBuf.Type>
private fun createReceiverTypeReferenceStub() {
receiverType?.let {
@@ -144,6 +144,9 @@ private class FunctionClsStubBuilder(
override val returnType: ProtoBuf.Type
get() = functionProto.returnType(c.typeTable)
override val contextReceiverTypes: List<ProtoBuf.Type>
get() = functionProto.contextReceiverTypes(c.typeTable)
override fun createValueParameterList() {
typeStubBuilder.createValueParameterListStub(callableStub, functionProto, functionProto.valueParameterList, protoContainer)
}
@@ -200,6 +203,9 @@ private class PropertyClsStubBuilder(
override val returnType: ProtoBuf.Type
get() = propertyProto.returnType(c.typeTable)
override val contextReceiverTypes: List<ProtoBuf.Type>
get() = propertyProto.contextReceiverTypes(c.typeTable)
override fun createValueParameterList() {
}
@@ -261,6 +267,9 @@ private class ConstructorClsStubBuilder(
override val returnType: ProtoBuf.Type?
get() = null
override val contextReceiverTypes: List<ProtoBuf.Type>
get() = emptyList()
override fun createValueParameterList() {
typeStubBuilder.createValueParameterListStub(callableStub, constructorProto, constructorProto.valueParameterList, protoContainer)
}
@@ -12,10 +12,7 @@ import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.Flags
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
import org.jetbrains.kotlin.metadata.deserialization.TypeTable
import org.jetbrains.kotlin.metadata.deserialization.supertypes
import org.jetbrains.kotlin.metadata.deserialization.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtClassBody
import org.jetbrains.kotlin.psi.KtSuperTypeEntry
@@ -57,6 +54,7 @@ private class ClassClsStubBuilder(
private val c = outerContext.child(
classProto.typeParameterList, classId.shortClassName, nameResolver, thisAsProtoContainer.typeTable, thisAsProtoContainer
)
private val contextReceiversListStubBuilder = ContextReceiversListStubBuilder(c)
private val typeStubBuilder = TypeClsStubBuilder(c)
private val supertypeIds = run {
val supertypeIds = classProto.supertypes(c.typeTable).map { c.nameResolver.getClassId(it.className) }
@@ -85,6 +83,7 @@ private class ClassClsStubBuilder(
private fun createClassOrObjectStubAndModifierListStub(): StubElement<out PsiElement> {
val classOrObjectStub = doCreateClassOrObjectStub()
contextReceiversListStubBuilder.createContextReceiverStubs(classOrObjectStub, classProto.contextReceiverTypes(c.typeTable))
val modifierList = createModifierListForClass(classOrObjectStub)
if (Flags.HAS_ANNOTATIONS.get(classProto.flags)) {
createAnnotationStubs(c.components.annotationLoader.loadClassAnnotations(thisAsProtoContainer), modifierList)
@@ -0,0 +1,28 @@
/*
* Copyright 2010-2022 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 com.intellij.psi.stubs.StubElement
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.psi.KtContextReceiver
import org.jetbrains.kotlin.psi.KtContextReceiverList
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
import org.jetbrains.kotlin.psi.stubs.impl.KotlinPlaceHolderStubImpl
internal class ContextReceiversListStubBuilder(c: ClsStubBuilderContext) {
private val typeStubBuilder = TypeClsStubBuilder(c)
fun createContextReceiverStubs(parent: StubElement<*>, contextReceiverTypes: List<ProtoBuf.Type>) {
if (contextReceiverTypes.isEmpty()) return
val contextReceiverListStub =
KotlinPlaceHolderStubImpl<KtContextReceiverList>(parent, KtStubElementTypes.CONTEXT_RECEIVER_LIST)
for (contextReceiverType in contextReceiverTypes) {
val contextReceiverStub =
KotlinPlaceHolderStubImpl<KtContextReceiver>(contextReceiverListStub, KtStubElementTypes.CONTEXT_RECEIVER)
typeStubBuilder.createTypeReferenceStub(contextReceiverStub, contextReceiverType)
}
}
}
@@ -28,7 +28,7 @@ object KotlinStubVersions {
// 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 = 78
private const val BINARY_STUB_VERSION = 79
// 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.