Move stub builder stuff from intellij
This is mechanical moving without fixing compilation errors, just packages are changes
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":compiler:psi"))
|
||||
api(project(":core:deserialization.common"))
|
||||
api(project(":core:deserialization.common.jvm"))
|
||||
api(project(":core:deserialization"))
|
||||
implementation(project(":core:compiler.common.jvm"))
|
||||
|
||||
api(intellijCoreDep()) { includeJars("intellij-core", rootProject = rootProject) }
|
||||
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"test" {}
|
||||
}
|
||||
|
||||
|
||||
+286
@@ -0,0 +1,286 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
package org.jetbrains.kotlin.psi.stubs.builder
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.stubs.StubElement
|
||||
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.name.Name
|
||||
import org.jetbrains.kotlin.psi.stubs.builder.flags.*
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
||||
import org.jetbrains.kotlin.psi.stubs.impl.KotlinFunctionStubImpl
|
||||
import org.jetbrains.kotlin.psi.stubs.impl.KotlinPlaceHolderStubImpl
|
||||
import org.jetbrains.kotlin.psi.stubs.impl.KotlinPropertyStubImpl
|
||||
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
|
||||
|
||||
fun createPackageDeclarationsStubs(
|
||||
parentStub: StubElement<out PsiElement>,
|
||||
outerContext: ClsStubBuilderContext,
|
||||
protoContainer: ProtoContainer.Package,
|
||||
packageProto: ProtoBuf.Package
|
||||
) {
|
||||
createDeclarationsStubs(parentStub, outerContext, protoContainer, packageProto.functionList, packageProto.propertyList)
|
||||
createTypeAliasesStubs(parentStub, outerContext, protoContainer, packageProto.typeAliasList)
|
||||
}
|
||||
|
||||
fun createDeclarationsStubs(
|
||||
parentStub: StubElement<out PsiElement>,
|
||||
outerContext: ClsStubBuilderContext,
|
||||
protoContainer: ProtoContainer,
|
||||
functionProtos: List<ProtoBuf.Function>,
|
||||
propertyProtos: List<ProtoBuf.Property>,
|
||||
) {
|
||||
for (propertyProto in propertyProtos) {
|
||||
if (!shouldSkip(propertyProto.flags, outerContext.nameResolver.getName(propertyProto.name))) {
|
||||
PropertyClsStubBuilder(parentStub, outerContext, protoContainer, propertyProto).build()
|
||||
}
|
||||
}
|
||||
for (functionProto in functionProtos) {
|
||||
if (!shouldSkip(functionProto.flags, outerContext.nameResolver.getName(functionProto.name))) {
|
||||
FunctionClsStubBuilder(parentStub, outerContext, protoContainer, functionProto).build()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createTypeAliasesStubs(
|
||||
parentStub: StubElement<out PsiElement>,
|
||||
outerContext: ClsStubBuilderContext,
|
||||
protoContainer: ProtoContainer,
|
||||
typeAliasesProtos: List<ProtoBuf.TypeAlias>
|
||||
) {
|
||||
for (typeAliasProto in typeAliasesProtos) {
|
||||
createTypeAliasStub(parentStub, typeAliasProto, protoContainer, outerContext)
|
||||
}
|
||||
}
|
||||
|
||||
fun createConstructorStub(
|
||||
parentStub: StubElement<out PsiElement>,
|
||||
constructorProto: ProtoBuf.Constructor,
|
||||
outerContext: ClsStubBuilderContext,
|
||||
protoContainer: ProtoContainer
|
||||
) {
|
||||
ConstructorClsStubBuilder(parentStub, outerContext, protoContainer, constructorProto).build()
|
||||
}
|
||||
|
||||
private fun shouldSkip(flags: Int, name: Name): Boolean {
|
||||
return when (Flags.MEMBER_KIND.get(flags)) {
|
||||
MemberKind.FAKE_OVERRIDE, MemberKind.DELEGATION -> true
|
||||
//TODO: fix decompiler to use sane criteria
|
||||
MemberKind.SYNTHESIZED -> !DataClassResolver.isComponentLike(name)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
abstract class CallableClsStubBuilder(
|
||||
parent: StubElement<out PsiElement>,
|
||||
outerContext: ClsStubBuilderContext,
|
||||
protected val protoContainer: ProtoContainer,
|
||||
private val typeParameters: List<ProtoBuf.TypeParameter>
|
||||
) {
|
||||
protected val c = outerContext.child(typeParameters)
|
||||
protected val typeStubBuilder = TypeClsStubBuilder(c)
|
||||
protected val isTopLevel: Boolean get() = protoContainer is ProtoContainer.Package
|
||||
protected val callableStub: StubElement<out PsiElement> by lazy(LazyThreadSafetyMode.NONE) { doCreateCallableStub(parent) }
|
||||
|
||||
fun build() {
|
||||
createModifierListStub()
|
||||
val typeConstraintListData = typeStubBuilder.createTypeParameterListStub(callableStub, typeParameters)
|
||||
createReceiverTypeReferenceStub()
|
||||
createValueParameterList()
|
||||
createReturnTypeStub()
|
||||
typeStubBuilder.createTypeConstraintListStub(callableStub, typeConstraintListData)
|
||||
}
|
||||
|
||||
abstract val receiverType: ProtoBuf.Type?
|
||||
abstract val receiverAnnotations: List<ClassIdWithTarget>
|
||||
|
||||
abstract val returnType: ProtoBuf.Type?
|
||||
|
||||
private fun createReceiverTypeReferenceStub() {
|
||||
receiverType?.let {
|
||||
typeStubBuilder.createTypeReferenceStub(callableStub, it, this::receiverAnnotations)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createReturnTypeStub() {
|
||||
returnType?.let {
|
||||
typeStubBuilder.createTypeReferenceStub(callableStub, it)
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun createModifierListStub()
|
||||
|
||||
abstract fun createValueParameterList()
|
||||
|
||||
abstract fun doCreateCallableStub(parent: StubElement<out PsiElement>): StubElement<out PsiElement>
|
||||
}
|
||||
|
||||
private class FunctionClsStubBuilder(
|
||||
parent: StubElement<out PsiElement>,
|
||||
outerContext: ClsStubBuilderContext,
|
||||
protoContainer: ProtoContainer,
|
||||
private val functionProto: ProtoBuf.Function
|
||||
) : CallableClsStubBuilder(parent, outerContext, protoContainer, functionProto.typeParameterList) {
|
||||
override val receiverType: ProtoBuf.Type?
|
||||
get() = functionProto.receiverType(c.typeTable)
|
||||
|
||||
override val receiverAnnotations: List<ClassIdWithTarget>
|
||||
get() {
|
||||
return c.components.annotationLoader
|
||||
.loadExtensionReceiverParameterAnnotations(protoContainer, functionProto, AnnotatedCallableKind.FUNCTION)
|
||||
.map { ClassIdWithTarget(it, AnnotationUseSiteTarget.RECEIVER) }
|
||||
}
|
||||
|
||||
override val returnType: ProtoBuf.Type
|
||||
get() = functionProto.returnType(c.typeTable)
|
||||
|
||||
override fun createValueParameterList() {
|
||||
typeStubBuilder.createValueParameterListStub(callableStub, functionProto, functionProto.valueParameterList, protoContainer)
|
||||
}
|
||||
|
||||
override fun createModifierListStub() {
|
||||
val modalityModifier = if (isTopLevel) listOf() else listOf(MODALITY)
|
||||
val modifierListStubImpl = createModifierListStubForDeclaration(
|
||||
callableStub, functionProto.flags,
|
||||
listOf(VISIBILITY, OPERATOR, INFIX, EXTERNAL_FUN, INLINE, TAILREC, SUSPEND) + modalityModifier
|
||||
)
|
||||
|
||||
// If function is marked as having no annotations, we don't create stubs for it
|
||||
if (!Flags.HAS_ANNOTATIONS.get(functionProto.flags)) return
|
||||
|
||||
val annotationIds = c.components.annotationLoader.loadCallableAnnotations(
|
||||
protoContainer, functionProto, AnnotatedCallableKind.FUNCTION
|
||||
)
|
||||
createAnnotationStubs(annotationIds, modifierListStubImpl)
|
||||
}
|
||||
|
||||
override fun doCreateCallableStub(parent: StubElement<out PsiElement>): StubElement<out PsiElement> {
|
||||
val callableName = c.nameResolver.getName(functionProto.name)
|
||||
|
||||
return KotlinFunctionStubImpl(
|
||||
parent,
|
||||
callableName.ref(),
|
||||
isTopLevel,
|
||||
c.containerFqName.child(callableName),
|
||||
isExtension = functionProto.hasReceiver(),
|
||||
hasBlockBody = true,
|
||||
hasBody = Flags.MODALITY.get(functionProto.flags) != Modality.ABSTRACT,
|
||||
hasTypeParameterListBeforeFunctionName = functionProto.typeParameterList.isNotEmpty(),
|
||||
mayHaveContract = functionProto.hasContract()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class PropertyClsStubBuilder(
|
||||
parent: StubElement<out PsiElement>,
|
||||
outerContext: ClsStubBuilderContext,
|
||||
protoContainer: ProtoContainer,
|
||||
private val propertyProto: ProtoBuf.Property
|
||||
) : CallableClsStubBuilder(parent, outerContext, protoContainer, propertyProto.typeParameterList) {
|
||||
private val isVar = Flags.IS_VAR.get(propertyProto.flags)
|
||||
|
||||
override val receiverType: ProtoBuf.Type?
|
||||
get() = propertyProto.receiverType(c.typeTable)
|
||||
|
||||
override val receiverAnnotations: List<ClassIdWithTarget>
|
||||
get() = c.components.annotationLoader
|
||||
.loadExtensionReceiverParameterAnnotations(protoContainer, propertyProto, AnnotatedCallableKind.PROPERTY_GETTER)
|
||||
.map { ClassIdWithTarget(it, AnnotationUseSiteTarget.RECEIVER) }
|
||||
|
||||
override val returnType: ProtoBuf.Type
|
||||
get() = propertyProto.returnType(c.typeTable)
|
||||
|
||||
override fun createValueParameterList() {
|
||||
}
|
||||
|
||||
override fun createModifierListStub() {
|
||||
val constModifier = if (isVar) listOf() else listOf(CONST)
|
||||
val modalityModifier = if (isTopLevel) listOf() else listOf(MODALITY)
|
||||
|
||||
val modifierListStubImpl = createModifierListStubForDeclaration(
|
||||
callableStub, propertyProto.flags,
|
||||
listOf(VISIBILITY, LATEINIT, EXTERNAL_PROPERTY) + constModifier + modalityModifier
|
||||
)
|
||||
|
||||
// If field is marked as having no annotations, we don't create stubs for it
|
||||
if (!Flags.HAS_ANNOTATIONS.get(propertyProto.flags)) return
|
||||
|
||||
val propertyAnnotations =
|
||||
c.components.annotationLoader.loadCallableAnnotations(protoContainer, propertyProto, AnnotatedCallableKind.PROPERTY)
|
||||
val backingFieldAnnotations =
|
||||
c.components.annotationLoader.loadPropertyBackingFieldAnnotations(protoContainer, propertyProto)
|
||||
val delegateFieldAnnotations =
|
||||
c.components.annotationLoader.loadPropertyDelegateFieldAnnotations(protoContainer, propertyProto)
|
||||
val allAnnotations =
|
||||
propertyAnnotations.map { ClassIdWithTarget(it, null) } +
|
||||
backingFieldAnnotations.map { ClassIdWithTarget(it, AnnotationUseSiteTarget.FIELD) } +
|
||||
delegateFieldAnnotations.map { ClassIdWithTarget(it, AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD) }
|
||||
createTargetedAnnotationStubs(allAnnotations, modifierListStubImpl)
|
||||
}
|
||||
|
||||
override fun doCreateCallableStub(parent: StubElement<out PsiElement>): StubElement<out PsiElement> {
|
||||
val callableName = c.nameResolver.getName(propertyProto.name)
|
||||
|
||||
return KotlinPropertyStubImpl(
|
||||
parent,
|
||||
callableName.ref(),
|
||||
isVar,
|
||||
isTopLevel,
|
||||
hasDelegate = false,
|
||||
hasDelegateExpression = false,
|
||||
hasInitializer = false,
|
||||
isExtension = propertyProto.hasReceiver(),
|
||||
hasReturnTypeRef = true,
|
||||
fqName = c.containerFqName.child(callableName)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class ConstructorClsStubBuilder(
|
||||
parent: StubElement<out PsiElement>,
|
||||
outerContext: ClsStubBuilderContext,
|
||||
protoContainer: ProtoContainer,
|
||||
private val constructorProto: ProtoBuf.Constructor
|
||||
) : CallableClsStubBuilder(parent, outerContext, protoContainer, emptyList()) {
|
||||
override val receiverType: ProtoBuf.Type?
|
||||
get() = null
|
||||
|
||||
override val receiverAnnotations: List<ClassIdWithTarget>
|
||||
get() = emptyList()
|
||||
|
||||
override val returnType: ProtoBuf.Type?
|
||||
get() = null
|
||||
|
||||
override fun createValueParameterList() {
|
||||
typeStubBuilder.createValueParameterListStub(callableStub, constructorProto, constructorProto.valueParameterList, protoContainer)
|
||||
}
|
||||
|
||||
override fun createModifierListStub() {
|
||||
val modifierListStubImpl = createModifierListStubForDeclaration(callableStub, constructorProto.flags, listOf(VISIBILITY))
|
||||
|
||||
// If constructor is marked as having no annotations, we don't create stubs for it
|
||||
if (!Flags.HAS_ANNOTATIONS.get(constructorProto.flags)) return
|
||||
|
||||
val annotationIds = c.components.annotationLoader.loadCallableAnnotations(
|
||||
protoContainer, constructorProto, AnnotatedCallableKind.FUNCTION
|
||||
)
|
||||
createAnnotationStubs(annotationIds, modifierListStubImpl)
|
||||
}
|
||||
|
||||
override fun doCreateCallableStub(parent: StubElement<out PsiElement>): StubElement<out PsiElement> {
|
||||
return if (Flags.IS_SECONDARY.get(constructorProto.flags))
|
||||
KotlinPlaceHolderStubImpl(parent, KtStubElementTypes.SECONDARY_CONSTRUCTOR)
|
||||
else
|
||||
KotlinPlaceHolderStubImpl(parent, KtStubElementTypes.PRIMARY_CONSTRUCTOR)
|
||||
}
|
||||
}
|
||||
+283
@@ -0,0 +1,283 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
package org.jetbrains.kotlin.psi.stubs.builder
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.stubs.StubElement
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.builtins.isNumberedFunctionClassFqName
|
||||
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.name.ClassId
|
||||
import org.jetbrains.kotlin.psi.KtClassBody
|
||||
import org.jetbrains.kotlin.psi.KtSuperTypeEntry
|
||||
import org.jetbrains.kotlin.psi.KtSuperTypeList
|
||||
import org.jetbrains.kotlin.psi.stubs.builder.flags.*
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtClassElementType
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
||||
import org.jetbrains.kotlin.psi.stubs.impl.KotlinClassStubImpl
|
||||
import org.jetbrains.kotlin.psi.stubs.impl.KotlinModifierListStubImpl
|
||||
import org.jetbrains.kotlin.psi.stubs.impl.KotlinObjectStubImpl
|
||||
import org.jetbrains.kotlin.psi.stubs.impl.KotlinPlaceHolderStubImpl
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getClassId
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||
|
||||
fun createClassStub(
|
||||
parent: StubElement<out PsiElement>,
|
||||
classProto: ProtoBuf.Class,
|
||||
nameResolver: NameResolver,
|
||||
classId: ClassId,
|
||||
source: SourceElement?,
|
||||
context: ClsStubBuilderContext
|
||||
) {
|
||||
ClassClsStubBuilder(parent, classProto, nameResolver, classId, source, context).build()
|
||||
}
|
||||
|
||||
private class ClassClsStubBuilder(
|
||||
private val parentStub: StubElement<out PsiElement>,
|
||||
private val classProto: ProtoBuf.Class,
|
||||
nameResolver: NameResolver,
|
||||
private val classId: ClassId,
|
||||
source: SourceElement?,
|
||||
outerContext: ClsStubBuilderContext
|
||||
) {
|
||||
private val thisAsProtoContainer = ProtoContainer.Class(
|
||||
classProto, nameResolver, TypeTable(classProto.typeTable), source, outerContext.protoContainer
|
||||
)
|
||||
private val classKind = thisAsProtoContainer.kind
|
||||
|
||||
private val c = outerContext.child(
|
||||
classProto.typeParameterList, classId.shortClassName, nameResolver, thisAsProtoContainer.typeTable, thisAsProtoContainer
|
||||
)
|
||||
private val typeStubBuilder = TypeClsStubBuilder(c)
|
||||
private val supertypeIds = run {
|
||||
val supertypeIds = classProto.supertypes(c.typeTable).map { c.nameResolver.getClassId(it.className) }
|
||||
//empty supertype list if single supertype is Any
|
||||
if (supertypeIds.singleOrNull()?.let { StandardNames.FqNames.any == it.asSingleFqName().toUnsafe() } == true) {
|
||||
listOf()
|
||||
} else {
|
||||
supertypeIds
|
||||
}
|
||||
}
|
||||
|
||||
private val companionObjectName = if (classProto.hasCompanionObjectName())
|
||||
c.nameResolver.getName(classProto.companionObjectName)
|
||||
else
|
||||
null
|
||||
|
||||
private val classOrObjectStub = createClassOrObjectStubAndModifierListStub()
|
||||
|
||||
fun build() {
|
||||
val typeConstraintListData = typeStubBuilder.createTypeParameterListStub(classOrObjectStub, classProto.typeParameterList)
|
||||
createConstructorStub()
|
||||
createDelegationSpecifierList()
|
||||
typeStubBuilder.createTypeConstraintListStub(classOrObjectStub, typeConstraintListData)
|
||||
createClassBodyAndMemberStubs()
|
||||
}
|
||||
|
||||
private fun createClassOrObjectStubAndModifierListStub(): StubElement<out PsiElement> {
|
||||
val classOrObjectStub = doCreateClassOrObjectStub()
|
||||
val modifierList = createModifierListForClass(classOrObjectStub)
|
||||
if (Flags.HAS_ANNOTATIONS.get(classProto.flags)) {
|
||||
createAnnotationStubs(c.components.annotationLoader.loadClassAnnotations(thisAsProtoContainer), modifierList)
|
||||
}
|
||||
return classOrObjectStub
|
||||
}
|
||||
|
||||
private fun createModifierListForClass(parent: StubElement<out PsiElement>): KotlinModifierListStubImpl {
|
||||
val relevantFlags = arrayListOf(VISIBILITY)
|
||||
relevantFlags.add(EXTERNAL_CLASS)
|
||||
if (isClass()) {
|
||||
relevantFlags.add(INNER)
|
||||
relevantFlags.add(DATA)
|
||||
relevantFlags.add(MODALITY)
|
||||
relevantFlags.add(VALUE_CLASS)
|
||||
}
|
||||
if (isInterface()) {
|
||||
relevantFlags.add(FUN_INTERFACE)
|
||||
}
|
||||
val additionalModifiers = when (classKind) {
|
||||
ProtoBuf.Class.Kind.ENUM_CLASS -> listOf(KtTokens.ENUM_KEYWORD)
|
||||
ProtoBuf.Class.Kind.COMPANION_OBJECT -> listOf(KtTokens.COMPANION_KEYWORD)
|
||||
ProtoBuf.Class.Kind.ANNOTATION_CLASS -> listOf(KtTokens.ANNOTATION_KEYWORD)
|
||||
else -> listOf<KtModifierKeywordToken>()
|
||||
}
|
||||
return createModifierListStubForDeclaration(parent, classProto.flags, relevantFlags, additionalModifiers)
|
||||
}
|
||||
|
||||
private fun doCreateClassOrObjectStub(): StubElement<out PsiElement> {
|
||||
val isCompanionObject = classKind == ProtoBuf.Class.Kind.COMPANION_OBJECT
|
||||
val fqName = classId.asSingleFqName()
|
||||
val shortName = fqName.shortName().ref()
|
||||
val superTypeRefs = supertypeIds.filterNot {
|
||||
//TODO: filtering function types should go away
|
||||
isNumberedFunctionClassFqName(it.asSingleFqName().toUnsafe())
|
||||
}.map { it.shortClassName.ref() }.toTypedArray()
|
||||
val classId = classId.takeUnless { it.isLocal }
|
||||
return when (classKind) {
|
||||
ProtoBuf.Class.Kind.OBJECT, ProtoBuf.Class.Kind.COMPANION_OBJECT -> {
|
||||
KotlinObjectStubImpl(
|
||||
parentStub, shortName, fqName,
|
||||
classId = classId,
|
||||
superTypeRefs,
|
||||
isTopLevel = !this.classId.isNestedClass,
|
||||
isDefault = isCompanionObject,
|
||||
isLocal = false,
|
||||
isObjectLiteral = false,
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
KotlinClassStubImpl(
|
||||
KtClassElementType.getStubType(classKind == ProtoBuf.Class.Kind.ENUM_ENTRY),
|
||||
parentStub,
|
||||
fqName.ref(),
|
||||
classId = classId,
|
||||
shortName,
|
||||
superTypeRefs,
|
||||
isInterface = classKind == ProtoBuf.Class.Kind.INTERFACE,
|
||||
isEnumEntry = classKind == ProtoBuf.Class.Kind.ENUM_ENTRY,
|
||||
isLocal = false,
|
||||
isTopLevel = !this.classId.isNestedClass,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createConstructorStub() {
|
||||
if (!isClass()) return
|
||||
|
||||
val primaryConstructorProto = classProto.constructorList.find { !Flags.IS_SECONDARY.get(it.flags) } ?: return
|
||||
|
||||
createConstructorStub(classOrObjectStub, primaryConstructorProto, c, thisAsProtoContainer)
|
||||
}
|
||||
|
||||
private fun createDelegationSpecifierList() {
|
||||
// if single supertype is any then no delegation specifier list is needed
|
||||
if (supertypeIds.isEmpty()) return
|
||||
|
||||
val delegationSpecifierListStub = KotlinPlaceHolderStubImpl<KtSuperTypeList>(classOrObjectStub, KtStubElementTypes.SUPER_TYPE_LIST)
|
||||
|
||||
classProto.supertypes(c.typeTable).forEach { type ->
|
||||
val superClassStub = KotlinPlaceHolderStubImpl<KtSuperTypeEntry>(
|
||||
delegationSpecifierListStub, KtStubElementTypes.SUPER_TYPE_ENTRY
|
||||
)
|
||||
typeStubBuilder.createTypeReferenceStub(superClassStub, type)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createClassBodyAndMemberStubs() {
|
||||
val classBody = KotlinPlaceHolderStubImpl<KtClassBody>(classOrObjectStub, KtStubElementTypes.CLASS_BODY)
|
||||
createEnumEntryStubs(classBody)
|
||||
createCompanionObjectStub(classBody)
|
||||
createCallableMemberStubs(classBody)
|
||||
createInnerAndNestedClasses(classBody)
|
||||
createTypeAliasesStubs(classBody)
|
||||
}
|
||||
|
||||
private fun createCompanionObjectStub(classBody: KotlinPlaceHolderStubImpl<KtClassBody>) {
|
||||
if (companionObjectName == null) {
|
||||
return
|
||||
}
|
||||
|
||||
val companionObjectId = classId.createNestedClassId(companionObjectName)
|
||||
createNestedClassStub(classBody, companionObjectId)
|
||||
}
|
||||
|
||||
private fun createEnumEntryStubs(classBody: KotlinPlaceHolderStubImpl<KtClassBody>) {
|
||||
if (classKind != ProtoBuf.Class.Kind.ENUM_CLASS) return
|
||||
|
||||
classProto.enumEntryList.forEach { entry ->
|
||||
val name = c.nameResolver.getName(entry.name)
|
||||
val annotations = c.components.annotationLoader.loadEnumEntryAnnotations(thisAsProtoContainer, entry)
|
||||
val enumEntryStub = KotlinClassStubImpl(
|
||||
KtStubElementTypes.ENUM_ENTRY,
|
||||
classBody,
|
||||
qualifiedName = c.containerFqName.child(name).ref(),
|
||||
classId = null, // enum entry do not have class id
|
||||
name = name.ref(),
|
||||
superNames = arrayOf(),
|
||||
isInterface = false,
|
||||
isEnumEntry = true,
|
||||
isLocal = false,
|
||||
isTopLevel = false
|
||||
)
|
||||
if (annotations.isNotEmpty()) {
|
||||
createAnnotationStubs(annotations, createEmptyModifierListStub(enumEntryStub))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createCallableMemberStubs(classBody: KotlinPlaceHolderStubImpl<KtClassBody>) {
|
||||
for (secondaryConstructorProto in classProto.constructorList) {
|
||||
if (Flags.IS_SECONDARY.get(secondaryConstructorProto.flags)) {
|
||||
createConstructorStub(classBody, secondaryConstructorProto, c, thisAsProtoContainer)
|
||||
}
|
||||
}
|
||||
|
||||
createDeclarationsStubs(classBody, c, thisAsProtoContainer, classProto.functionList, classProto.propertyList)
|
||||
}
|
||||
|
||||
private fun isClass(): Boolean {
|
||||
return classKind == ProtoBuf.Class.Kind.CLASS ||
|
||||
classKind == ProtoBuf.Class.Kind.ENUM_CLASS ||
|
||||
classKind == ProtoBuf.Class.Kind.ANNOTATION_CLASS
|
||||
}
|
||||
|
||||
private fun isInterface(): Boolean {
|
||||
return classKind == ProtoBuf.Class.Kind.INTERFACE
|
||||
}
|
||||
|
||||
private fun createInnerAndNestedClasses(classBody: KotlinPlaceHolderStubImpl<KtClassBody>) {
|
||||
classProto.nestedClassNameList.forEach { id ->
|
||||
val nestedClassName = c.nameResolver.getName(id)
|
||||
if (nestedClassName != companionObjectName) {
|
||||
val nestedClassId = classId.createNestedClassId(nestedClassName)
|
||||
createNestedClassStub(classBody, nestedClassId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createTypeAliasesStubs(classBody: KotlinPlaceHolderStubImpl<KtClassBody>) {
|
||||
createTypeAliasesStubs(classBody, c, thisAsProtoContainer, classProto.typeAliasList)
|
||||
}
|
||||
|
||||
private fun createNestedClassStub(classBody: StubElement<out PsiElement>, nestedClassId: ClassId) {
|
||||
val (nameResolver, classProto, _, sourceElement) =
|
||||
c.components.classDataFinder.findClassData(nestedClassId)
|
||||
?: c.components.virtualFileForDebug.let { rootFile ->
|
||||
val outerClassId = nestedClassId.outerClassId
|
||||
val sortedChildren = rootFile.parent.children.sortedBy { it.name }
|
||||
val msgPrefix = "Could not find data for nested class $nestedClassId of class $outerClassId\n"
|
||||
val explanation = when {
|
||||
outerClassId != null && sortedChildren.none { it.name.startsWith("${outerClassId.relativeClassName}\$a") } ->
|
||||
// KT-29427: case with obfuscation
|
||||
"Reason: obfuscation suspected (single-letter name)\n"
|
||||
else ->
|
||||
// General case
|
||||
""
|
||||
}
|
||||
val msg = msgPrefix + explanation +
|
||||
"Root file: ${rootFile.canonicalPath}\n" +
|
||||
"Dir: ${rootFile.parent.canonicalPath}\n" +
|
||||
"Children:\n" +
|
||||
sortedChildren.joinToString(separator = "\n") {
|
||||
"${it.name} (valid: ${it.isValid})"
|
||||
}
|
||||
LOG.info(msg)
|
||||
return
|
||||
}
|
||||
createClassStub(classBody, classProto, nameResolver, nestedClassId, sourceElement, c)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LOG = Logger.getInstance(ClassClsStubBuilder::class.java)
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
package org.jetbrains.kotlin.psi.stubs.builder
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.metadata.deserialization.TypeTable
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.serialization.deserialization.AnnotationAndConstantLoader
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||
|
||||
data class ClassIdWithTarget(val classId: ClassId, val target: AnnotationUseSiteTarget?)
|
||||
|
||||
class ClsStubBuilderComponents(
|
||||
val classDataFinder: ClassDataFinder,
|
||||
val annotationLoader: AnnotationAndConstantLoader<ClassId, Unit>,
|
||||
val virtualFileForDebug: VirtualFile
|
||||
) {
|
||||
fun createContext(
|
||||
nameResolver: NameResolver,
|
||||
packageFqName: FqName,
|
||||
typeTable: TypeTable
|
||||
): ClsStubBuilderContext =
|
||||
ClsStubBuilderContext(this, nameResolver, packageFqName, EmptyTypeParameters, typeTable, protoContainer = null)
|
||||
}
|
||||
|
||||
interface TypeParameters {
|
||||
operator fun get(id: Int): Name
|
||||
|
||||
fun child(nameResolver: NameResolver, innerTypeParameters: List<ProtoBuf.TypeParameter>) =
|
||||
TypeParametersImpl(nameResolver, innerTypeParameters, parent = this)
|
||||
}
|
||||
|
||||
object EmptyTypeParameters : TypeParameters {
|
||||
override fun get(id: Int): Name = throw IllegalStateException("Unknown type parameter with id = $id")
|
||||
}
|
||||
|
||||
class TypeParametersImpl(
|
||||
nameResolver: NameResolver,
|
||||
typeParameterProtos: Collection<ProtoBuf.TypeParameter>,
|
||||
private val parent: TypeParameters
|
||||
) : TypeParameters {
|
||||
private val typeParametersById = typeParameterProtos.map { Pair(it.id, nameResolver.getName(it.name)) }.toMap()
|
||||
|
||||
override fun get(id: Int): Name = typeParametersById[id] ?: parent[id]
|
||||
}
|
||||
|
||||
class ClsStubBuilderContext(
|
||||
val components: ClsStubBuilderComponents,
|
||||
val nameResolver: NameResolver,
|
||||
val containerFqName: FqName,
|
||||
val typeParameters: TypeParameters,
|
||||
val typeTable: TypeTable,
|
||||
val protoContainer: ProtoContainer.Class?
|
||||
)
|
||||
|
||||
internal fun ClsStubBuilderContext.child(
|
||||
typeParameterList: List<ProtoBuf.TypeParameter>,
|
||||
name: Name? = null,
|
||||
nameResolver: NameResolver = this.nameResolver,
|
||||
typeTable: TypeTable = this.typeTable,
|
||||
protoContainer: ProtoContainer.Class? = this.protoContainer
|
||||
): ClsStubBuilderContext = ClsStubBuilderContext(
|
||||
this.components,
|
||||
nameResolver,
|
||||
if (name != null) this.containerFqName.child(name) else this.containerFqName,
|
||||
this.typeParameters.child(nameResolver, typeParameterList),
|
||||
typeTable,
|
||||
protoContainer
|
||||
)
|
||||
+344
@@ -0,0 +1,344 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
package org.jetbrains.kotlin.psi.stubs.builder
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.stubs.StubElement
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.builtins.isBuiltinFunctionClass
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf.Type
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf.Type.Argument.Projection
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf.TypeParameter.Variance
|
||||
import org.jetbrains.kotlin.metadata.deserialization.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.protobuf.MessageLite
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinUserTypeStub
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
||||
import org.jetbrains.kotlin.psi.stubs.impl.*
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getClassId
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||
import org.jetbrains.kotlin.serialization.js.DynamicTypeDeserializer
|
||||
import org.jetbrains.kotlin.utils.doNothing
|
||||
import java.util.*
|
||||
|
||||
// TODO: see DescriptorRendererOptions.excludedTypeAnnotationClasses for decompiler
|
||||
private val ANNOTATIONS_NOT_LOADED_FOR_TYPES = setOf(StandardNames.FqNames.parameterName)
|
||||
|
||||
class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
|
||||
fun createTypeReferenceStub(
|
||||
parent: StubElement<out PsiElement>,
|
||||
type: Type,
|
||||
additionalAnnotations: () -> List<ClassIdWithTarget> = { emptyList() }
|
||||
) {
|
||||
val abbreviatedType = type.abbreviatedType(c.typeTable)
|
||||
if (abbreviatedType != null) {
|
||||
return createTypeReferenceStub(parent, abbreviatedType, additionalAnnotations)
|
||||
}
|
||||
|
||||
val typeReference = KotlinPlaceHolderStubImpl<KtTypeReference>(parent, KtStubElementTypes.TYPE_REFERENCE)
|
||||
|
||||
val annotations = c.components.annotationLoader.loadTypeAnnotations(type, c.nameResolver).filterNot {
|
||||
val isTopLevelClass = !it.isNestedClass
|
||||
isTopLevelClass && it.asSingleFqName() in ANNOTATIONS_NOT_LOADED_FOR_TYPES
|
||||
}
|
||||
|
||||
val allAnnotations = additionalAnnotations() + annotations.map { ClassIdWithTarget(it, null) }
|
||||
|
||||
when {
|
||||
type.hasClassName() || type.hasTypeAliasName() ->
|
||||
createClassReferenceTypeStub(typeReference, type, allAnnotations)
|
||||
type.hasTypeParameter() ->
|
||||
createTypeParameterStub(typeReference, type, c.typeParameters[type.typeParameter], allAnnotations)
|
||||
type.hasTypeParameterName() ->
|
||||
createTypeParameterStub(typeReference, type, c.nameResolver.getName(type.typeParameterName), allAnnotations)
|
||||
else -> {
|
||||
doNothing()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun nullableTypeParent(parent: KotlinStubBaseImpl<*>, type: Type): KotlinStubBaseImpl<*> = if (type.nullable)
|
||||
KotlinPlaceHolderStubImpl<KtNullableType>(parent, KtStubElementTypes.NULLABLE_TYPE)
|
||||
else
|
||||
parent
|
||||
|
||||
private fun createTypeParameterStub(parent: KotlinStubBaseImpl<*>, type: Type, name: Name, annotations: List<ClassIdWithTarget>) {
|
||||
createTypeAnnotationStubs(parent, type, annotations)
|
||||
val nullableParentWrapper = nullableTypeParent(parent, type)
|
||||
createStubForTypeName(ClassId.topLevel(FqName.topLevel(name)), nullableParentWrapper)
|
||||
}
|
||||
|
||||
private fun createClassReferenceTypeStub(parent: KotlinStubBaseImpl<*>, type: Type, annotations: List<ClassIdWithTarget>) {
|
||||
if (type.hasFlexibleTypeCapabilitiesId()) {
|
||||
val id = c.nameResolver.getString(type.flexibleTypeCapabilitiesId)
|
||||
|
||||
if (id == DynamicTypeDeserializer.id) {
|
||||
KotlinPlaceHolderStubImpl<KtDynamicType>(nullableTypeParent(parent, type), KtStubElementTypes.DYNAMIC_TYPE)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
assert(type.hasClassName() || type.hasTypeAliasName()) {
|
||||
"Class reference stub must have either class or type alias name"
|
||||
}
|
||||
|
||||
val classId = c.nameResolver.getClassId(if (type.hasClassName()) type.className else type.typeAliasName)
|
||||
val shouldBuildAsFunctionType = isBuiltinFunctionClass(classId) && type.argumentList.none { it.projection == Projection.STAR }
|
||||
if (shouldBuildAsFunctionType) {
|
||||
val (extensionAnnotations, notExtensionAnnotations) = annotations.partition {
|
||||
it.classId.asSingleFqName() == StandardNames.FqNames.extensionFunctionType
|
||||
}
|
||||
|
||||
val isExtension = extensionAnnotations.isNotEmpty()
|
||||
val isSuspend = Flags.SUSPEND_TYPE.get(type.flags)
|
||||
|
||||
val nullableWrapper = if (isSuspend) {
|
||||
val wrapper = nullableTypeParent(parent, type)
|
||||
createTypeAnnotationStubs(wrapper, type, notExtensionAnnotations)
|
||||
wrapper
|
||||
} else {
|
||||
createTypeAnnotationStubs(parent, type, notExtensionAnnotations)
|
||||
nullableTypeParent(parent, type)
|
||||
}
|
||||
|
||||
createFunctionTypeStub(nullableWrapper, type, isExtension, isSuspend)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
createTypeAnnotationStubs(parent, type, annotations)
|
||||
|
||||
val outerTypeChain = generateSequence(type) { it.outerType(c.typeTable) }.toList()
|
||||
|
||||
createStubForTypeName(classId, nullableTypeParent(parent, type)) { userTypeStub, index ->
|
||||
outerTypeChain.getOrNull(index)?.let { createTypeArgumentListStub(userTypeStub, it.argumentList) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun createTypeAnnotationStubs(parent: KotlinStubBaseImpl<*>, type: Type, annotations: List<ClassIdWithTarget>) {
|
||||
val typeModifiers = getTypeModifiersAsWritten(type)
|
||||
if (annotations.isEmpty() && typeModifiers.isEmpty()) return
|
||||
val typeModifiersMask = ModifierMaskUtils.computeMask { it in typeModifiers }
|
||||
val modifiersList = KotlinModifierListStubImpl(parent, typeModifiersMask, KtStubElementTypes.MODIFIER_LIST)
|
||||
createTargetedAnnotationStubs(annotations, modifiersList)
|
||||
}
|
||||
|
||||
private fun getTypeModifiersAsWritten(type: Type): Set<KtModifierKeywordToken> {
|
||||
if (!type.hasClassName() && !type.hasTypeAliasName()) return emptySet()
|
||||
|
||||
val result = hashSetOf<KtModifierKeywordToken>()
|
||||
|
||||
if (Flags.SUSPEND_TYPE.get(type.flags)) {
|
||||
result.add(KtTokens.SUSPEND_KEYWORD)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun createTypeArgumentListStub(typeStub: KotlinUserTypeStub, typeArgumentProtoList: List<Type.Argument>) {
|
||||
if (typeArgumentProtoList.isEmpty()) {
|
||||
return
|
||||
}
|
||||
val typeArgumentsListStub = KotlinPlaceHolderStubImpl<KtTypeArgumentList>(typeStub, KtStubElementTypes.TYPE_ARGUMENT_LIST)
|
||||
typeArgumentProtoList.forEach { typeArgumentProto ->
|
||||
val projectionKind = typeArgumentProto.projection.toProjectionKind()
|
||||
val typeProjection = KotlinTypeProjectionStubImpl(typeArgumentsListStub, projectionKind.ordinal)
|
||||
if (projectionKind != KtProjectionKind.STAR) {
|
||||
val modifierKeywordToken = projectionKind.token as? KtModifierKeywordToken
|
||||
createModifierListStub(typeProjection, listOfNotNull(modifierKeywordToken))
|
||||
createTypeReferenceStub(typeProjection, typeArgumentProto.type(c.typeTable)!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Projection.toProjectionKind() = when (this) {
|
||||
Projection.IN -> KtProjectionKind.IN
|
||||
Projection.OUT -> KtProjectionKind.OUT
|
||||
Projection.INV -> KtProjectionKind.NONE
|
||||
Projection.STAR -> KtProjectionKind.STAR
|
||||
}
|
||||
|
||||
private fun createFunctionTypeStub(
|
||||
parent: StubElement<out PsiElement>,
|
||||
type: Type,
|
||||
isExtensionFunctionType: Boolean,
|
||||
isSuspend: Boolean
|
||||
) {
|
||||
val typeArgumentList = type.argumentList
|
||||
val functionType = KotlinPlaceHolderStubImpl<KtFunctionType>(parent, KtStubElementTypes.FUNCTION_TYPE)
|
||||
if (isExtensionFunctionType) {
|
||||
val functionTypeReceiverStub =
|
||||
KotlinPlaceHolderStubImpl<KtFunctionTypeReceiver>(functionType, KtStubElementTypes.FUNCTION_TYPE_RECEIVER)
|
||||
val receiverTypeProto = typeArgumentList.first().type(c.typeTable)!!
|
||||
createTypeReferenceStub(functionTypeReceiverStub, receiverTypeProto)
|
||||
}
|
||||
|
||||
val parameterList = KotlinPlaceHolderStubImpl<KtParameterList>(functionType, KtStubElementTypes.VALUE_PARAMETER_LIST)
|
||||
val typeArgumentsWithoutReceiverAndReturnType =
|
||||
typeArgumentList.subList(if (isExtensionFunctionType) 1 else 0, typeArgumentList.size - 1)
|
||||
var suspendParameterType: Type? = null
|
||||
|
||||
for ((index, argument) in typeArgumentsWithoutReceiverAndReturnType.withIndex()) {
|
||||
if (isSuspend && index == typeArgumentsWithoutReceiverAndReturnType.size - 1) {
|
||||
val parameterType = argument.type(c.typeTable)!!
|
||||
if (parameterType.hasClassName() && parameterType.argumentCount == 1) {
|
||||
val classId = c.nameResolver.getClassId(parameterType.className)
|
||||
val fqName = classId.asSingleFqName()
|
||||
assert(
|
||||
fqName == FqName("kotlin.coroutines.Continuation") ||
|
||||
fqName == FqName("kotlin.coroutines.experimental.Continuation")
|
||||
) {
|
||||
"Last parameter type of suspend function must be Continuation, but it is $fqName"
|
||||
}
|
||||
suspendParameterType = parameterType
|
||||
continue
|
||||
}
|
||||
}
|
||||
val parameter = KotlinParameterStubImpl(
|
||||
parameterList, fqName = null, name = null, isMutable = false, hasValOrVar = false, hasDefaultValue = false
|
||||
)
|
||||
|
||||
createTypeReferenceStub(parameter, argument.type(c.typeTable)!!)
|
||||
}
|
||||
|
||||
|
||||
if (suspendParameterType == null) {
|
||||
val returnType = typeArgumentList.last().type(c.typeTable)!!
|
||||
createTypeReferenceStub(functionType, returnType)
|
||||
} else {
|
||||
val continuationArgumentType = suspendParameterType.getArgument(0).type(c.typeTable)!!
|
||||
createTypeReferenceStub(functionType, continuationArgumentType)
|
||||
}
|
||||
}
|
||||
|
||||
fun createValueParameterListStub(
|
||||
parent: StubElement<out PsiElement>,
|
||||
callableProto: MessageLite,
|
||||
parameters: List<ProtoBuf.ValueParameter>,
|
||||
container: ProtoContainer
|
||||
) {
|
||||
val parameterListStub = KotlinPlaceHolderStubImpl<KtParameterList>(parent, KtStubElementTypes.VALUE_PARAMETER_LIST)
|
||||
for ((index, valueParameterProto) in parameters.withIndex()) {
|
||||
val name = c.nameResolver.getName(valueParameterProto.name)
|
||||
val parameterStub = KotlinParameterStubImpl(
|
||||
parameterListStub,
|
||||
name = name.ref(),
|
||||
fqName = null,
|
||||
hasDefaultValue = false,
|
||||
hasValOrVar = false,
|
||||
isMutable = false
|
||||
)
|
||||
val varargElementType = valueParameterProto.varargElementType(c.typeTable)
|
||||
val typeProto = varargElementType ?: valueParameterProto.type(c.typeTable)
|
||||
val modifiers = arrayListOf<KtModifierKeywordToken>()
|
||||
|
||||
if (varargElementType != null) {
|
||||
modifiers.add(KtTokens.VARARG_KEYWORD)
|
||||
}
|
||||
if (Flags.IS_CROSSINLINE.get(valueParameterProto.flags)) {
|
||||
modifiers.add(KtTokens.CROSSINLINE_KEYWORD)
|
||||
}
|
||||
if (Flags.IS_NOINLINE.get(valueParameterProto.flags)) {
|
||||
modifiers.add(KtTokens.NOINLINE_KEYWORD)
|
||||
}
|
||||
|
||||
val modifierList = createModifierListStub(parameterStub, modifiers)
|
||||
|
||||
if (Flags.HAS_ANNOTATIONS.get(valueParameterProto.flags)) {
|
||||
val parameterAnnotations = c.components.annotationLoader.loadValueParameterAnnotations(
|
||||
container, callableProto, callableProto.annotatedCallableKind, index, valueParameterProto
|
||||
)
|
||||
if (parameterAnnotations.isNotEmpty()) {
|
||||
createAnnotationStubs(parameterAnnotations, modifierList ?: createEmptyModifierListStub(parameterStub))
|
||||
}
|
||||
}
|
||||
|
||||
createTypeReferenceStub(parameterStub, typeProto)
|
||||
}
|
||||
}
|
||||
|
||||
fun createTypeParameterListStub(
|
||||
parent: StubElement<out PsiElement>,
|
||||
typeParameterProtoList: List<ProtoBuf.TypeParameter>
|
||||
): List<Pair<Name, Type>> {
|
||||
if (typeParameterProtoList.isEmpty()) return listOf()
|
||||
|
||||
val typeParameterListStub = KotlinPlaceHolderStubImpl<KtTypeParameterList>(parent, KtStubElementTypes.TYPE_PARAMETER_LIST)
|
||||
val protosForTypeConstraintList = arrayListOf<Pair<Name, Type>>()
|
||||
for (proto in typeParameterProtoList) {
|
||||
val name = c.nameResolver.getName(proto.name)
|
||||
val typeParameterStub = KotlinTypeParameterStubImpl(
|
||||
typeParameterListStub,
|
||||
name = name.ref(),
|
||||
isInVariance = proto.variance == Variance.IN,
|
||||
isOutVariance = proto.variance == Variance.OUT
|
||||
)
|
||||
createTypeParameterModifierListStub(typeParameterStub, proto)
|
||||
val upperBoundProtos = proto.upperBounds(c.typeTable)
|
||||
if (upperBoundProtos.isNotEmpty()) {
|
||||
val upperBound = upperBoundProtos.first()
|
||||
if (!upperBound.isDefaultUpperBound()) {
|
||||
createTypeReferenceStub(typeParameterStub, upperBound)
|
||||
}
|
||||
protosForTypeConstraintList.addAll(upperBoundProtos.drop(1).map { Pair(name, it) })
|
||||
}
|
||||
}
|
||||
return protosForTypeConstraintList
|
||||
}
|
||||
|
||||
fun createTypeConstraintListStub(
|
||||
parent: StubElement<out PsiElement>,
|
||||
protosForTypeConstraintList: List<Pair<Name, Type>>
|
||||
) {
|
||||
if (protosForTypeConstraintList.isEmpty()) {
|
||||
return
|
||||
}
|
||||
val typeConstraintListStub = KotlinPlaceHolderStubImpl<KtTypeConstraintList>(parent, KtStubElementTypes.TYPE_CONSTRAINT_LIST)
|
||||
for ((name, type) in protosForTypeConstraintList) {
|
||||
val typeConstraintStub = KotlinPlaceHolderStubImpl<KtTypeConstraint>(typeConstraintListStub, KtStubElementTypes.TYPE_CONSTRAINT)
|
||||
KotlinNameReferenceExpressionStubImpl(typeConstraintStub, name.ref())
|
||||
createTypeReferenceStub(typeConstraintStub, type)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createTypeParameterModifierListStub(
|
||||
typeParameterStub: KotlinTypeParameterStubImpl,
|
||||
typeParameterProto: ProtoBuf.TypeParameter
|
||||
) {
|
||||
val modifiers = ArrayList<KtModifierKeywordToken>()
|
||||
when (typeParameterProto.variance) {
|
||||
Variance.IN -> modifiers.add(KtTokens.IN_KEYWORD)
|
||||
Variance.OUT -> modifiers.add(KtTokens.OUT_KEYWORD)
|
||||
Variance.INV -> { /* do nothing */
|
||||
}
|
||||
null -> { /* do nothing */
|
||||
}
|
||||
}
|
||||
if (typeParameterProto.reified) {
|
||||
modifiers.add(KtTokens.REIFIED_KEYWORD)
|
||||
}
|
||||
|
||||
val modifierList = createModifierListStub(typeParameterStub, modifiers)
|
||||
|
||||
val annotations = c.components.annotationLoader.loadTypeParameterAnnotations(typeParameterProto, c.nameResolver)
|
||||
if (annotations.isNotEmpty()) {
|
||||
createAnnotationStubs(
|
||||
annotations,
|
||||
modifierList ?: createEmptyModifierListStub(typeParameterStub)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Type.isDefaultUpperBound(): Boolean {
|
||||
return this.hasClassName() &&
|
||||
c.nameResolver.getClassId(className).let { StandardNames.FqNames.any == it.asSingleFqName().toUnsafe() } &&
|
||||
this.nullable
|
||||
}
|
||||
}
|
||||
+232
@@ -0,0 +1,232 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
package org.jetbrains.kotlin.psi.stubs.builder
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.stubs.StubElement
|
||||
import com.intellij.util.io.StringRef
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.psi.stubs.builder.flags.FlagsToModifiers
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinFileStubForIde
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.TypeTable
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.protobuf.MessageLite
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinUserTypeStub
|
||||
import org.jetbrains.kotlin.psi.stubs.builder.*
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
||||
import org.jetbrains.kotlin.psi.stubs.impl.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.serialization.deserialization.AnnotatedCallableKind
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
|
||||
|
||||
fun createTopLevelClassStub(
|
||||
classId: ClassId,
|
||||
classProto: ProtoBuf.Class,
|
||||
source: SourceElement?,
|
||||
context: ClsStubBuilderContext,
|
||||
isScript: Boolean
|
||||
): KotlinFileStubImpl {
|
||||
val fileStub = createFileStub(classId.packageFqName, isScript)
|
||||
createClassStub(fileStub, classProto, context.nameResolver, classId, source, context)
|
||||
return fileStub
|
||||
}
|
||||
|
||||
fun createPackageFacadeStub(
|
||||
packageProto: ProtoBuf.Package,
|
||||
packageFqName: FqName,
|
||||
c: ClsStubBuilderContext
|
||||
): KotlinFileStubImpl {
|
||||
val fileStub = KotlinFileStubForIde.forFile(packageFqName, isScript = false)
|
||||
setupFileStub(fileStub, packageFqName)
|
||||
createPackageDeclarationsStubs(
|
||||
fileStub, c, ProtoContainer.Package(packageFqName, c.nameResolver, c.typeTable, source = null), packageProto
|
||||
)
|
||||
return fileStub
|
||||
}
|
||||
|
||||
fun createFileFacadeStub(
|
||||
packageProto: ProtoBuf.Package,
|
||||
facadeFqName: FqName,
|
||||
c: ClsStubBuilderContext
|
||||
): KotlinFileStubImpl {
|
||||
val packageFqName = facadeFqName.parent()
|
||||
val fileStub = KotlinFileStubForIde.forFileFacadeStub(facadeFqName)
|
||||
setupFileStub(fileStub, packageFqName)
|
||||
val container = ProtoContainer.Package(
|
||||
packageFqName, c.nameResolver, c.typeTable,
|
||||
JvmPackagePartSource(JvmClassName.byClassId(ClassId.topLevel(facadeFqName)), null, packageProto, c.nameResolver)
|
||||
)
|
||||
createPackageDeclarationsStubs(fileStub, c, container, packageProto)
|
||||
return fileStub
|
||||
}
|
||||
|
||||
fun createMultifileClassStub(
|
||||
header: KotlinClassHeader,
|
||||
partFiles: List<KotlinJvmBinaryClass>,
|
||||
facadeFqName: FqName,
|
||||
components: ClsStubBuilderComponents
|
||||
): KotlinFileStubImpl {
|
||||
val packageFqName = header.packageName?.let { FqName(it) } ?: facadeFqName.parent()
|
||||
val partNames = header.data?.asList()?.map { it.substringAfterLast('/') }
|
||||
val fileStub = KotlinFileStubForIde.forMultifileClassStub(facadeFqName, partNames)
|
||||
setupFileStub(fileStub, packageFqName)
|
||||
for (partFile in partFiles) {
|
||||
val partHeader = partFile.classHeader
|
||||
val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(partHeader.data!!, partHeader.strings!!)
|
||||
val partContext = components.createContext(nameResolver, packageFqName, TypeTable(packageProto.typeTable))
|
||||
val container = ProtoContainer.Package(
|
||||
packageFqName, partContext.nameResolver, partContext.typeTable,
|
||||
JvmPackagePartSource(partFile, packageProto, nameResolver)
|
||||
)
|
||||
createPackageDeclarationsStubs(fileStub, partContext, container, packageProto)
|
||||
}
|
||||
return fileStub
|
||||
}
|
||||
|
||||
fun createIncompatibleAbiVersionFileStub() = createFileStub(FqName.ROOT, isScript = false)
|
||||
|
||||
fun createFileStub(packageFqName: FqName, isScript: Boolean): KotlinFileStubImpl {
|
||||
val fileStub = KotlinFileStubForIde.forFile(packageFqName, isScript)
|
||||
setupFileStub(fileStub, packageFqName)
|
||||
return fileStub
|
||||
}
|
||||
|
||||
private fun setupFileStub(fileStub: KotlinFileStubImpl, packageFqName: FqName) {
|
||||
val packageDirectiveStub = KotlinPlaceHolderStubImpl<KtPackageDirective>(fileStub, KtStubElementTypes.PACKAGE_DIRECTIVE)
|
||||
createStubForPackageName(packageDirectiveStub, packageFqName)
|
||||
KotlinPlaceHolderStubImpl<KtImportList>(fileStub, KtStubElementTypes.IMPORT_LIST)
|
||||
}
|
||||
|
||||
fun createStubForPackageName(packageDirectiveStub: KotlinPlaceHolderStubImpl<KtPackageDirective>, packageFqName: FqName) {
|
||||
val segments = packageFqName.pathSegments()
|
||||
val iterator = segments.listIterator(segments.size)
|
||||
|
||||
fun recCreateStubForPackageName(current: StubElement<out PsiElement>) {
|
||||
when (iterator.previousIndex()) {
|
||||
-1 -> return
|
||||
0 -> {
|
||||
KotlinNameReferenceExpressionStubImpl(current, iterator.previous().ref())
|
||||
return
|
||||
}
|
||||
else -> {
|
||||
val lastSegment = iterator.previous()
|
||||
val receiver = KotlinPlaceHolderStubImpl<KtDotQualifiedExpression>(current, KtStubElementTypes.DOT_QUALIFIED_EXPRESSION)
|
||||
recCreateStubForPackageName(receiver)
|
||||
KotlinNameReferenceExpressionStubImpl(receiver, lastSegment.ref())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recCreateStubForPackageName(packageDirectiveStub)
|
||||
}
|
||||
|
||||
fun createStubForTypeName(
|
||||
typeClassId: ClassId,
|
||||
parent: StubElement<out PsiElement>,
|
||||
bindTypeArguments: (KotlinUserTypeStub, Int) -> Unit = { _, _ -> }
|
||||
): KotlinUserTypeStub {
|
||||
val substituteWithAny = typeClassId.isLocal
|
||||
|
||||
val fqName = if (substituteWithAny) StandardNames.FqNames.any
|
||||
else typeClassId.asSingleFqName().toUnsafe()
|
||||
|
||||
val segments = fqName.pathSegments().asReversed()
|
||||
assert(segments.isNotEmpty())
|
||||
|
||||
fun recCreateStubForType(current: StubElement<out PsiElement>, level: Int): KotlinUserTypeStub {
|
||||
val lastSegment = segments[level]
|
||||
val userTypeStub = KotlinUserTypeStubImpl(current)
|
||||
if (level + 1 < segments.size) {
|
||||
recCreateStubForType(userTypeStub, level + 1)
|
||||
}
|
||||
KotlinNameReferenceExpressionStubImpl(userTypeStub, lastSegment.ref())
|
||||
if (!substituteWithAny) {
|
||||
bindTypeArguments(userTypeStub, level)
|
||||
}
|
||||
return userTypeStub
|
||||
}
|
||||
|
||||
return recCreateStubForType(parent, level = 0)
|
||||
}
|
||||
|
||||
fun createModifierListStubForDeclaration(
|
||||
parent: StubElement<out PsiElement>,
|
||||
flags: Int,
|
||||
flagsToTranslate: List<FlagsToModifiers> = listOf(),
|
||||
additionalModifiers: List<KtModifierKeywordToken> = listOf()
|
||||
): KotlinModifierListStubImpl {
|
||||
assert(flagsToTranslate.isNotEmpty())
|
||||
|
||||
val modifiers = flagsToTranslate.mapNotNull { it.getModifiers(flags) } + additionalModifiers
|
||||
return createModifierListStub(parent, modifiers)!!
|
||||
}
|
||||
|
||||
fun createModifierListStub(
|
||||
parent: StubElement<out PsiElement>,
|
||||
modifiers: Collection<KtModifierKeywordToken>
|
||||
): KotlinModifierListStubImpl? {
|
||||
if (modifiers.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
return KotlinModifierListStubImpl(
|
||||
parent,
|
||||
ModifierMaskUtils.computeMask { it in modifiers },
|
||||
KtStubElementTypes.MODIFIER_LIST
|
||||
)
|
||||
}
|
||||
|
||||
fun createEmptyModifierListStub(parent: KotlinStubBaseImpl<*>): KotlinModifierListStubImpl {
|
||||
return KotlinModifierListStubImpl(
|
||||
parent,
|
||||
ModifierMaskUtils.computeMask { false },
|
||||
KtStubElementTypes.MODIFIER_LIST
|
||||
)
|
||||
}
|
||||
|
||||
fun createAnnotationStubs(annotationIds: List<ClassId>, parent: KotlinStubBaseImpl<*>) {
|
||||
return createTargetedAnnotationStubs(annotationIds.map { ClassIdWithTarget(it, null) }, parent)
|
||||
}
|
||||
|
||||
fun createTargetedAnnotationStubs(
|
||||
annotationIds: List<ClassIdWithTarget>,
|
||||
parent: KotlinStubBaseImpl<*>
|
||||
) {
|
||||
if (annotationIds.isEmpty()) return
|
||||
|
||||
annotationIds.forEach { annotation ->
|
||||
val (annotationClassId, target) = annotation
|
||||
val annotationEntryStubImpl = KotlinAnnotationEntryStubImpl(
|
||||
parent,
|
||||
shortName = annotationClassId.shortClassName.ref(),
|
||||
hasValueArguments = false
|
||||
)
|
||||
if (target != null) {
|
||||
KotlinAnnotationUseSiteTargetStubImpl(annotationEntryStubImpl, StringRef.fromString(target.name)!!)
|
||||
}
|
||||
val constructorCallee =
|
||||
KotlinPlaceHolderStubImpl<KtConstructorCalleeExpression>(annotationEntryStubImpl, KtStubElementTypes.CONSTRUCTOR_CALLEE)
|
||||
val typeReference = KotlinPlaceHolderStubImpl<KtTypeReference>(constructorCallee, KtStubElementTypes.TYPE_REFERENCE)
|
||||
createStubForTypeName(annotationClassId, typeReference)
|
||||
}
|
||||
}
|
||||
|
||||
val MessageLite.annotatedCallableKind: AnnotatedCallableKind
|
||||
get() = when (this) {
|
||||
is ProtoBuf.Property -> AnnotatedCallableKind.PROPERTY
|
||||
is ProtoBuf.Function, is ProtoBuf.Constructor -> AnnotatedCallableKind.FUNCTION
|
||||
else -> throw IllegalStateException("Unsupported message: $this")
|
||||
}
|
||||
|
||||
fun Name.ref() = StringRef.fromString(this.asString())!!
|
||||
|
||||
fun FqName.ref() = StringRef.fromString(this.asString())!!
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
package org.jetbrains.kotlin.psi.stubs.builder.flags
|
||||
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||
import org.jetbrains.kotlin.lexer.KtToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.Flags
|
||||
|
||||
abstract class FlagsToModifiers {
|
||||
abstract fun getModifiers(flags: Int): KtModifierKeywordToken?
|
||||
}
|
||||
|
||||
val MODALITY: FlagsToModifiers = object : FlagsToModifiers() {
|
||||
override fun getModifiers(flags: Int): KtModifierKeywordToken {
|
||||
val modality = Flags.MODALITY.get(flags)
|
||||
return when (modality) {
|
||||
ProtoBuf.Modality.ABSTRACT -> KtTokens.ABSTRACT_KEYWORD
|
||||
ProtoBuf.Modality.FINAL -> KtTokens.FINAL_KEYWORD
|
||||
ProtoBuf.Modality.OPEN -> KtTokens.OPEN_KEYWORD
|
||||
ProtoBuf.Modality.SEALED -> KtTokens.SEALED_KEYWORD
|
||||
null -> throw IllegalStateException("Unexpected modality: null")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val VISIBILITY: FlagsToModifiers = object : FlagsToModifiers() {
|
||||
override fun getModifiers(flags: Int): KtModifierKeywordToken? {
|
||||
val visibility = Flags.VISIBILITY.get(flags)
|
||||
return when (visibility) {
|
||||
ProtoBuf.Visibility.PRIVATE, ProtoBuf.Visibility.PRIVATE_TO_THIS -> KtTokens.PRIVATE_KEYWORD
|
||||
ProtoBuf.Visibility.INTERNAL -> KtTokens.INTERNAL_KEYWORD
|
||||
ProtoBuf.Visibility.PROTECTED -> KtTokens.PROTECTED_KEYWORD
|
||||
ProtoBuf.Visibility.PUBLIC -> KtTokens.PUBLIC_KEYWORD
|
||||
else -> throw IllegalStateException("Unexpected visibility: $visibility")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val INNER = createBooleanFlagToModifier(Flags.IS_INNER, KtTokens.INNER_KEYWORD)
|
||||
val CONST = createBooleanFlagToModifier(Flags.IS_CONST, KtTokens.CONST_KEYWORD)
|
||||
val LATEINIT = createBooleanFlagToModifier(Flags.IS_LATEINIT, KtTokens.LATEINIT_KEYWORD)
|
||||
val OPERATOR = createBooleanFlagToModifier(Flags.IS_OPERATOR, KtTokens.OPERATOR_KEYWORD)
|
||||
val INFIX = createBooleanFlagToModifier(Flags.IS_INFIX, KtTokens.INFIX_KEYWORD)
|
||||
val DATA = createBooleanFlagToModifier(Flags.IS_DATA, KtTokens.DATA_KEYWORD)
|
||||
val EXTERNAL_FUN = createBooleanFlagToModifier(Flags.IS_EXTERNAL_FUNCTION, KtTokens.EXTERNAL_KEYWORD)
|
||||
val EXTERNAL_PROPERTY = createBooleanFlagToModifier(Flags.IS_EXTERNAL_PROPERTY, KtTokens.EXTERNAL_KEYWORD)
|
||||
val EXTERNAL_CLASS = createBooleanFlagToModifier(Flags.IS_EXTERNAL_CLASS, KtTokens.EXTERNAL_KEYWORD)
|
||||
val INLINE = createBooleanFlagToModifier(Flags.IS_INLINE, KtTokens.INLINE_KEYWORD)
|
||||
val VALUE_CLASS = createBooleanFlagToModifier(Flags.IS_INLINE_CLASS, KtTokens.VALUE_KEYWORD)
|
||||
val FUN_INTERFACE = createBooleanFlagToModifier(Flags.IS_FUN_INTERFACE, KtTokens.FUN_KEYWORD)
|
||||
val TAILREC = createBooleanFlagToModifier(Flags.IS_TAILREC, KtTokens.TAILREC_KEYWORD)
|
||||
val SUSPEND = createBooleanFlagToModifier(Flags.IS_SUSPEND, KtTokens.SUSPEND_KEYWORD)
|
||||
|
||||
private fun createBooleanFlagToModifier(
|
||||
flagField: Flags.BooleanFlagField, ktModifierKeywordToken: KtModifierKeywordToken
|
||||
): FlagsToModifiers = BooleanFlagToModifier(flagField, ktModifierKeywordToken)
|
||||
|
||||
private class BooleanFlagToModifier(
|
||||
private val flagField: Flags.BooleanFlagField,
|
||||
private val ktModifierKeywordToken: KtModifierKeywordToken
|
||||
) : FlagsToModifiers() {
|
||||
override fun getModifiers(flags: Int): KtModifierKeywordToken? = if (flagField.get(flags)) ktModifierKeywordToken else null
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
package org.jetbrains.kotlin.psi.stubs.builder
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.stubs.StubElement
|
||||
import org.jetbrains.kotlin.psi.stubs.builder.flags.VISIBILITY
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.Flags
|
||||
import org.jetbrains.kotlin.metadata.deserialization.underlyingType
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.psi.stubs.impl.KotlinTypeAliasStubImpl
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getClassId
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||
|
||||
fun createTypeAliasStub(
|
||||
parent: StubElement<out PsiElement>,
|
||||
typeAliasProto: ProtoBuf.TypeAlias,
|
||||
protoContainer: ProtoContainer,
|
||||
outerContext: ClsStubBuilderContext
|
||||
) {
|
||||
val c = outerContext.child(typeAliasProto.typeParameterList)
|
||||
val shortName = c.nameResolver.getName(typeAliasProto.name)
|
||||
|
||||
val classId = when (protoContainer) {
|
||||
is ProtoContainer.Class -> protoContainer.classId.createNestedClassId(shortName)
|
||||
is ProtoContainer.Package -> ClassId.topLevel(protoContainer.fqName.child(shortName))
|
||||
}
|
||||
|
||||
val typeAlias = KotlinTypeAliasStubImpl(
|
||||
parent, classId.shortClassName.ref(), classId.asSingleFqName().ref(), classId,
|
||||
isTopLevel = !classId.isNestedClass
|
||||
)
|
||||
|
||||
val modifierList = createModifierListStubForDeclaration(typeAlias, typeAliasProto.flags, arrayListOf(VISIBILITY), listOf())
|
||||
|
||||
val typeStubBuilder = TypeClsStubBuilder(c)
|
||||
val restConstraints = typeStubBuilder.createTypeParameterListStub(typeAlias, typeAliasProto.typeParameterList)
|
||||
assert(restConstraints.isEmpty()) {
|
||||
"'where' constraints are not allowed for type aliases"
|
||||
}
|
||||
|
||||
if (Flags.HAS_ANNOTATIONS.get(typeAliasProto.flags)) {
|
||||
createAnnotationStubs(typeAliasProto.annotationList.map { c.nameResolver.getClassId(it.id) }, modifierList)
|
||||
}
|
||||
|
||||
val typeAliasUnderlyingType = typeAliasProto.underlyingType(c.typeTable)
|
||||
typeStubBuilder.createTypeReferenceStub(typeAlias, typeAliasUnderlyingType)
|
||||
}
|
||||
+4
-1
@@ -112,7 +112,6 @@ include ":benchmarks",
|
||||
":compiler:resolution.common.jvm",
|
||||
":compiler:resolution",
|
||||
":compiler:serialization",
|
||||
":compiler:psi",
|
||||
":compiler:visualizer",
|
||||
":compiler:visualizer:common",
|
||||
":compiler:visualizer:render-fir",
|
||||
@@ -292,6 +291,10 @@ include ":benchmarks",
|
||||
":kotlin-serialization-unshaded",
|
||||
":wasm:wasm.ir"
|
||||
|
||||
include ":compiler:psi",
|
||||
":compiler:psi:cls-psi-stub-builder"
|
||||
|
||||
|
||||
include ":kotlinx-atomicfu-compiler-plugin",
|
||||
":kotlinx-atomicfu-runtime",
|
||||
":atomicfu"
|
||||
|
||||
Reference in New Issue
Block a user