Support type aliases in stub builder

This commit is contained in:
Denis Zharkov
2016-06-27 18:23:42 +03:00
parent daa356860c
commit e24f0653fb
14 changed files with 262 additions and 14 deletions
@@ -51,10 +51,10 @@ class KotlinBuiltInStubBuilder : ClsStubBuilder() {
val context = components.createContext(nameResolver, packageFqName, TypeTable(packageProto.typeTable))
val fileStub = createFileStub(packageFqName)
createCallableStubs(
createDeclarationsStubs(
fileStub, context,
ProtoContainer.Package(packageFqName, context.nameResolver, context.typeTable, source = null),
packageProto.functionList, packageProto.propertyList
packageProto
)
for (classProto in file.classesToDecompile) {
createClassStub(
@@ -31,12 +31,23 @@ import org.jetbrains.kotlin.serialization.ProtoBuf.MemberKind
import org.jetbrains.kotlin.serialization.ProtoBuf.Modality
import org.jetbrains.kotlin.serialization.deserialization.*
fun createCallableStubs(
fun createDeclarationsStubs(
parentStub: StubElement<out PsiElement>,
outerContext: ClsStubBuilderContext,
protoContainer: ProtoContainer,
packageProto: ProtoBuf.Package
) {
createDeclarationsStubs(
parentStub, outerContext, protoContainer, packageProto.functionList, packageProto.propertyList, packageProto.typeAliasList)
}
fun createDeclarationsStubs(
parentStub: StubElement<out PsiElement>,
outerContext: ClsStubBuilderContext,
protoContainer: ProtoContainer,
functionProtos: List<ProtoBuf.Function>,
propertyProtos: List<ProtoBuf.Property>
propertyProtos: List<ProtoBuf.Property>,
typeAliasesProtos: List<ProtoBuf.TypeAlias>
) {
for (propertyProto in propertyProtos) {
if (!shouldSkip(propertyProto.flags, outerContext.nameResolver.getName(propertyProto.name))) {
@@ -48,6 +59,10 @@ fun createCallableStubs(
FunctionClsStubBuilder(parentStub, outerContext, protoContainer, functionProto).build()
}
}
for (typeAliasProto in typeAliasesProtos) {
createTypeAliasStub(parentStub, typeAliasProto, protoContainer, outerContext)
}
}
fun createConstructorStub(
@@ -226,7 +226,8 @@ private class ClassClsStubBuilder(
}
}
createCallableStubs(classBody, c, thisAsProtoContainer, classProto.functionList, classProto.propertyList)
createDeclarationsStubs(
classBody, c, thisAsProtoContainer, classProto.functionList, classProto.propertyList, classProto.typeAliasList)
}
private fun isClass(): Boolean {
@@ -44,6 +44,7 @@ import java.util.*
class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
fun createTypeReferenceStub(parent: StubElement<out PsiElement>, type: Type) {
if (type.hasAbbreviatedType()) return createTypeReferenceStub(parent, type.abbreviatedType)
val typeReference = KotlinPlaceHolderStubImpl<KtTypeReference>(parent, KtStubElementTypes.TYPE_REFERENCE)
val annotations = c.components.annotationLoader.loadTypeAnnotations(type, c.nameResolver).filterNot {
@@ -61,7 +62,7 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
}
when {
type.hasClassName() -> createClassReferenceTypeStub(effectiveParent, type, annotations)
type.hasClassName() || type.hasTypeAliasName() -> createClassReferenceTypeStub(effectiveParent, type, annotations)
type.hasTypeParameter() -> createTypeParameterStub(c.typeParameters[type.typeParameter])
type.hasTypeParameterName() -> createTypeParameterStub(c.nameResolver.getName(type.typeParameterName))
}
@@ -77,7 +78,11 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
}
}
val classId = c.nameResolver.getClassId(type.className)
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 = isNumberedFunctionClassFqName(classId.asSingleFqName().toUnsafe())
&& type.argumentList.none { it.projection == Projection.STAR }
if (shouldBuildAsFunctionType) {
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.idea.decompiler.stubBuilder.flags.FlagsToModifiers
import org.jetbrains.kotlin.idea.stubindex.KotlinFileStubForIde
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
@@ -37,7 +36,6 @@ 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.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.serialization.Flags
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.AnnotatedCallableKind
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
@@ -62,8 +60,8 @@ fun createPackageFacadeStub(
): KotlinFileStubImpl {
val fileStub = KotlinFileStubForIde.forFile(packageFqName, packageFqName.isRoot)
setupFileStub(fileStub, packageFqName)
createCallableStubs(fileStub, c, ProtoContainer.Package(packageFqName, c.nameResolver, c.typeTable, source = null),
packageProto.functionList, packageProto.propertyList)
createDeclarationsStubs(
fileStub, c, ProtoContainer.Package(packageFqName, c.nameResolver, c.typeTable, source = null), packageProto)
return fileStub
}
@@ -78,7 +76,7 @@ fun createFileFacadeStub(
val container = ProtoContainer.Package(
packageFqName, c.nameResolver, c.typeTable, JvmPackagePartSource(JvmClassName.byClassId(ClassId.topLevel(facadeFqName)), null)
)
createCallableStubs(fileStub, c, container, packageProto.functionList, packageProto.propertyList)
createDeclarationsStubs(fileStub, c, container, packageProto)
return fileStub
}
@@ -98,7 +96,7 @@ fun createMultifileClassStub(
val partContext = components.createContext(nameResolver, packageFqName, TypeTable(packageProto.typeTable))
val container = ProtoContainer.Package(packageFqName, partContext.nameResolver, partContext.typeTable,
JvmPackagePartSource(partFile))
createCallableStubs(fileStub, partContext, container, packageProto.functionList, packageProto.propertyList)
createDeclarationsStubs(fileStub, partContext, container, packageProto)
}
return fileStub
}
@@ -0,0 +1,63 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.decompiler.stubBuilder
import com.intellij.psi.PsiElement
import com.intellij.psi.stubs.StubElement
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.idea.decompiler.stubBuilder.flags.VISIBILITY
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.stubs.impl.KotlinTypeAliasStubImpl
import org.jetbrains.kotlin.serialization.Flags
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
import org.jetbrains.kotlin.serialization.deserialization.TypeTable
fun createTypeAliasStub(
parent: StubElement<out PsiElement>,
typeAliasProto: ProtoBuf.TypeAlias,
protoContainer: ProtoContainer,
context: ClsStubBuilderContext
) {
val shortName = context.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(),
isTopLevel = !classId.isNestedClass)
createModifierListStubForDeclaration(typeAlias, typeAliasProto.flags, arrayListOf(VISIBILITY), listOf())
val typeStubBuilder = TypeClsStubBuilder(context)
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)) {
// TODO: support annotations
// createAnnotationStubs(context.components.annotationLoader.loadClassAnnotations(thisAsProtoContainer), modifierList)
}
typeStubBuilder.createTypeReferenceStub(typeAlias, typeAliasProto.underlyingType)
}