Build kotlin stubs for compiled Kotlin files
This means that JetPsi would be built for compiled kotlin files
This commit is contained in:
+1
-1
@@ -106,7 +106,7 @@ public class JetClassElementType extends JetStubElementType<KotlinClassStub, Jet
|
|||||||
StubIndexServiceFactory.getInstance().indexClass(stub, sink);
|
StubIndexServiceFactory.getInstance().indexClass(stub, sink);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JetClassElementType getStubType(boolean isEnumEntry) {
|
public static JetClassElementType getStubType(boolean isEnumEntry) {
|
||||||
return isEnumEntry ? JetStubElementTypes.ENUM_ENTRY : JetStubElementTypes.CLASS;
|
return isEnumEntry ? JetStubElementTypes.ENUM_ENTRY : JetStubElementTypes.CLASS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import com.intellij.psi.PsiManager;
|
|||||||
import com.intellij.psi.compiled.ClassFileDecompilers;
|
import com.intellij.psi.compiled.ClassFileDecompilers;
|
||||||
import com.intellij.psi.compiled.ClsStubBuilder;
|
import com.intellij.psi.compiled.ClsStubBuilder;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.plugin.decompiler.stubBuilder.KotlinClsStubBuilder;
|
||||||
|
|
||||||
public class JetClassFileDecompiler extends ClassFileDecompilers.Full {
|
public class JetClassFileDecompiler extends ClassFileDecompilers.Full {
|
||||||
private final ClsStubBuilder stubBuilder = new KotlinClsStubBuilder();
|
private final ClsStubBuilder stubBuilder = new KotlinClsStubBuilder();
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2014 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.jet.plugin.decompiler
|
|
||||||
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
|
||||||
import com.intellij.psi.compiled.ClsStubBuilder
|
|
||||||
import com.intellij.psi.impl.compiled.ClassFileStubBuilder
|
|
||||||
import com.intellij.psi.impl.compiled.ClsFileImpl
|
|
||||||
import com.intellij.psi.stubs.PsiFileStub
|
|
||||||
import com.intellij.util.cls.ClsFormatException
|
|
||||||
import com.intellij.util.indexing.FileContent
|
|
||||||
|
|
||||||
public class KotlinClsStubBuilder : ClsStubBuilder() {
|
|
||||||
override fun getStubVersion() = ClassFileStubBuilder.STUB_VERSION + 1
|
|
||||||
|
|
||||||
throws(javaClass<ClsFormatException>())
|
|
||||||
override fun buildFileStub(content: FileContent): PsiFileStub<*>? {
|
|
||||||
val file = content.getFile()
|
|
||||||
|
|
||||||
if (isKotlinInternalCompiledFile(file)) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return ClsFileImpl.buildFileStub(file, content.getContent())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+143
@@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2014 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.jet.plugin.decompiler.stubBuilder
|
||||||
|
|
||||||
|
import com.intellij.psi.stubs.StubElement
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.ProtoBuf
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.Flags
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.ProtoBuf.Modality
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinFunctionStubImpl
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinPropertyStubImpl
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable.CallableKind
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.descriptors.ProtoContainer
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable.MemberKind
|
||||||
|
import org.jetbrains.jet.lang.resolve.dataClassUtils.isComponentLike
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.NameResolver
|
||||||
|
import org.jetbrains.jet.plugin.decompiler.stubBuilder.FlagsToModifiers.*
|
||||||
|
|
||||||
|
fun createCallableStub(
|
||||||
|
parentStub: StubElement<out PsiElement>,
|
||||||
|
callableProto: ProtoBuf.Callable,
|
||||||
|
outerContext: ClsStubBuilderContext,
|
||||||
|
protoContainer: ProtoContainer
|
||||||
|
) {
|
||||||
|
if (!shouldSkip(callableProto, outerContext.nameResolver)) {
|
||||||
|
CallableClsStubBuilder(parentStub, callableProto, outerContext, protoContainer).build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun shouldSkip(callableProto: ProtoBuf.Callable, nameResolver: NameResolver): Boolean {
|
||||||
|
val memberKind = Flags.MEMBER_KIND[callableProto.getFlags()]
|
||||||
|
return when (memberKind) {
|
||||||
|
MemberKind.FAKE_OVERRIDE, MemberKind.DELEGATION -> true
|
||||||
|
//TODO: fix decompiler to use sane criteria
|
||||||
|
MemberKind.SYNTHESIZED -> !isComponentLike(nameResolver.getName(callableProto.getName()))
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CallableClsStubBuilder(
|
||||||
|
private val parent: StubElement<out PsiElement>,
|
||||||
|
private val callableProto: ProtoBuf.Callable,
|
||||||
|
outerContext: ClsStubBuilderContext,
|
||||||
|
private val protoContainer: ProtoContainer
|
||||||
|
) {
|
||||||
|
private val c = outerContext.child(callableProto.getTypeParameterList())
|
||||||
|
private val typeStubBuilder = TypeClsStubBuilder(c)
|
||||||
|
private val isTopLevel: Boolean get() = protoContainer.packageFqName != null
|
||||||
|
private val callableStub = doCreateCallableStub()
|
||||||
|
|
||||||
|
fun build() {
|
||||||
|
createModifierListStub()
|
||||||
|
val typeConstraintListData = typeStubBuilder.createTypeParameterListStub(callableStub, callableProto.getTypeParameterList())
|
||||||
|
createReceiverTypeReferenceStub()
|
||||||
|
createValueParameterList()
|
||||||
|
createReturnTypeStub()
|
||||||
|
typeStubBuilder.createTypeConstraintListStub(callableStub, typeConstraintListData)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createValueParameterList() {
|
||||||
|
typeStubBuilder.createValueParameterListStub(callableStub, callableProto, protoContainer)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createReceiverTypeReferenceStub() {
|
||||||
|
if (callableProto.hasReceiverType()) {
|
||||||
|
typeStubBuilder.createTypeReferenceStub(callableStub, callableProto.getReceiverType())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createReturnTypeStub() {
|
||||||
|
typeStubBuilder.createTypeReferenceStub(callableStub, callableProto.getReturnType())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createModifierListStub() {
|
||||||
|
val relevantModifiers = if (isTopLevel) listOf(VISIBILITY) else listOf(VISIBILITY, MODALITY)
|
||||||
|
|
||||||
|
val modifierListStubImpl = createModifierListStubForDeclaration(callableStub, callableProto.getFlags(), relevantModifiers)
|
||||||
|
val annotationIds = c.components.annotationLoader.loadCallableAnnotations(
|
||||||
|
protoContainer, callableProto, c.nameResolver, callableProto.annotatedCallableKind
|
||||||
|
)
|
||||||
|
createAnnotationStubs(annotationIds, modifierListStubImpl)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doCreateCallableStub(): StubElement<out PsiElement> {
|
||||||
|
val callableKind = Flags.CALLABLE_KIND[callableProto.getFlags()]
|
||||||
|
val callableName = c.nameResolver.getName(callableProto.getName())
|
||||||
|
val callableFqName = c.memberFqNameProvider.getMemberFqName(callableName)
|
||||||
|
|
||||||
|
return when (callableKind) {
|
||||||
|
ProtoBuf.Callable.CallableKind.FUN -> {
|
||||||
|
KotlinFunctionStubImpl(
|
||||||
|
parent,
|
||||||
|
callableName.ref(),
|
||||||
|
isTopLevel,
|
||||||
|
callableFqName,
|
||||||
|
isExtension = callableProto.hasReceiverType(),
|
||||||
|
hasBlockBody = true,
|
||||||
|
hasBody = Flags.MODALITY[callableProto.getFlags()] != Modality.ABSTRACT,
|
||||||
|
hasTypeParameterListBeforeFunctionName = callableProto.getTypeParameterList().isNotEmpty(),
|
||||||
|
isProbablyNothingType = isProbablyNothing(callableProto)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ProtoBuf.Callable.CallableKind.VAL, ProtoBuf.Callable.CallableKind.VAR -> {
|
||||||
|
KotlinPropertyStubImpl(
|
||||||
|
parent,
|
||||||
|
callableName.ref(),
|
||||||
|
isVar = callableKind == CallableKind.VAR,
|
||||||
|
isTopLevel = isTopLevel,
|
||||||
|
hasDelegate = false,
|
||||||
|
hasDelegateExpression = false,
|
||||||
|
hasInitializer = false,
|
||||||
|
hasReceiverTypeRef = callableProto.hasReceiverType(),
|
||||||
|
hasReturnTypeRef = true,
|
||||||
|
fqName = callableFqName,
|
||||||
|
isProbablyNothingType = isProbablyNothing(callableProto)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ProtoBuf.Callable.CallableKind.CONSTRUCTOR -> throw IllegalStateException("Should not be called for constructor!")
|
||||||
|
else -> throw IllegalStateException("Unknown callable kind $callableKind")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: remove isProbablyNothing from stubs
|
||||||
|
private fun isProbablyNothing(callableProto: ProtoBuf.Callable): Boolean {
|
||||||
|
val constructor = callableProto.getReturnType().getConstructor()
|
||||||
|
return constructor.getKind() == ProtoBuf.Type.Constructor.Kind.CLASS &&
|
||||||
|
c.nameResolver.getClassId(constructor.getId()).getRelativeClassName().shortName().asString() == "Nothing"
|
||||||
|
}
|
||||||
|
}
|
||||||
+233
@@ -0,0 +1,233 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2014 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.jet.plugin.decompiler.stubBuilder
|
||||||
|
|
||||||
|
import com.intellij.psi.stubs.StubElement
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.Flags
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.ProtoBuf
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.elements.JetClassElementType
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinClassStubImpl
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinObjectStubImpl
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.jet.lang.psi.JetClassBody
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinPlaceHolderStubImpl
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes
|
||||||
|
import org.jetbrains.jet.lang.psi.JetParameterList
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.ClassId
|
||||||
|
import org.jetbrains.jet.lang.psi.JetDelegationSpecifierList
|
||||||
|
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperClass
|
||||||
|
import org.jetbrains.jet.lexer.JetTokens
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.SpecialNames.getClassObjectName
|
||||||
|
import org.jetbrains.jet.lang.psi.JetClassObject
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.descriptors.ProtoContainer
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinModifierListStubImpl
|
||||||
|
import org.jetbrains.jet.lexer.JetModifierKeywordToken
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.ProtoBuf.Type
|
||||||
|
import org.jetbrains.jet.plugin.decompiler.stubBuilder.FlagsToModifiers.*
|
||||||
|
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||||
|
|
||||||
|
|
||||||
|
fun createClassStub(parent: StubElement<out PsiElement>, classProto: ProtoBuf.Class, classId: ClassId, context: ClsStubBuilderContext) {
|
||||||
|
ClassClsStubBuilder(parent, classProto, classId, context).build()
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ClassClsStubBuilder(
|
||||||
|
private val parentStub: StubElement<out PsiElement>,
|
||||||
|
private val classProto: ProtoBuf.Class,
|
||||||
|
private val classId: ClassId,
|
||||||
|
private val outerContext: ClsStubBuilderContext
|
||||||
|
) {
|
||||||
|
private val c = outerContext.child(classProto.getTypeParameterList(), classId.getRelativeClassName().shortName())
|
||||||
|
private val typeStubBuilder = TypeClsStubBuilder(c)
|
||||||
|
private val classKind = Flags.CLASS_KIND[classProto.getFlags()]
|
||||||
|
private val supertypeIds = classProto.getSupertypeList().map {
|
||||||
|
type ->
|
||||||
|
assert(type.getConstructor().getKind() == Type.Constructor.Kind.CLASS)
|
||||||
|
c.nameResolver.getClassId(type.getConstructor().getId())
|
||||||
|
}.let {
|
||||||
|
supertypeIds ->
|
||||||
|
//empty supertype list if single supertype is Any
|
||||||
|
if (supertypeIds.singleOrNull()?.let { KotlinBuiltIns.isAny(it.asSingleFqName()) } ?: false) {
|
||||||
|
listOf()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
supertypeIds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val classOrObjectStub = createClassOrObjectStubAndModifierListStub()
|
||||||
|
|
||||||
|
fun build() {
|
||||||
|
val typeConstraintListData = typeStubBuilder.createTypeParameterListStub(classOrObjectStub, classProto.getTypeParameterList())
|
||||||
|
createConstructorStub()
|
||||||
|
createDelegationSpecifierList()
|
||||||
|
typeStubBuilder.createTypeConstraintListStub(classOrObjectStub, typeConstraintListData)
|
||||||
|
createClassBodyAndMemberStubs()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createClassOrObjectStubAndModifierListStub(): StubElement<out PsiElement> {
|
||||||
|
val isClassObject = classKind == ProtoBuf.Class.Kind.CLASS_OBJECT
|
||||||
|
if (isClassObject) {
|
||||||
|
val classObjectStub = KotlinPlaceHolderStubImpl<JetClassObject>(parentStub, JetStubElementTypes.CLASS_OBJECT)
|
||||||
|
val modifierList = createModifierListForClass(classObjectStub)
|
||||||
|
val objectDeclarationStub = doCreateClassOrObjectStub(classObjectStub)
|
||||||
|
createAnnotationStubs(c.components.annotationLoader.loadClassAnnotations(classProto, c.nameResolver), modifierList)
|
||||||
|
return objectDeclarationStub
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val classOrObjectStub = doCreateClassOrObjectStub(parentStub)
|
||||||
|
val modifierList = createModifierListForClass(classOrObjectStub)
|
||||||
|
createAnnotationStubs(c.components.annotationLoader.loadClassAnnotations(classProto, c.nameResolver), modifierList)
|
||||||
|
return classOrObjectStub
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createModifierListForClass(parent: StubElement<out PsiElement>): KotlinModifierListStubImpl {
|
||||||
|
val relevantFlags = arrayListOf(VISIBILITY)
|
||||||
|
if (isClass()) {
|
||||||
|
relevantFlags.add(INNER)
|
||||||
|
relevantFlags.add(MODALITY)
|
||||||
|
}
|
||||||
|
val additionalModifiers = when (classKind) {
|
||||||
|
ProtoBuf.Class.Kind.ENUM_CLASS -> listOf(JetTokens.ENUM_KEYWORD)
|
||||||
|
ProtoBuf.Class.Kind.ANNOTATION_CLASS -> listOf(JetTokens.ANNOTATION_KEYWORD)
|
||||||
|
else -> listOf<JetModifierKeywordToken>()
|
||||||
|
}
|
||||||
|
return createModifierListStubForDeclaration(parent, classProto.getFlags(), relevantFlags, additionalModifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doCreateClassOrObjectStub(parent: StubElement<out PsiElement>): StubElement<out PsiElement> {
|
||||||
|
val isClassObject = classKind == ProtoBuf.Class.Kind.CLASS_OBJECT
|
||||||
|
val fqName = if (!isClassObject) outerContext.memberFqNameProvider.getMemberFqName(classId.getRelativeClassName().shortName()) else null
|
||||||
|
val shortName = fqName?.shortName()?.ref()
|
||||||
|
val superTypeRefs = supertypeIds.filter {
|
||||||
|
//TODO: filtering function types should go away
|
||||||
|
!KotlinBuiltIns.isExactFunctionType(it.asSingleFqName()) && !KotlinBuiltIns.isExactExtensionFunctionType(it.asSingleFqName())
|
||||||
|
}.map { it.getRelativeClassName().shortName().ref() }.copyToArray()
|
||||||
|
return when (classKind) {
|
||||||
|
ProtoBuf.Class.Kind.OBJECT, ProtoBuf.Class.Kind.CLASS_OBJECT -> {
|
||||||
|
KotlinObjectStubImpl(
|
||||||
|
parent, shortName, fqName, superTypeRefs,
|
||||||
|
isTopLevel = classId.isTopLevelClass(),
|
||||||
|
isClassObject = isClassObject,
|
||||||
|
isLocal = false,
|
||||||
|
isObjectLiteral = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
KotlinClassStubImpl(
|
||||||
|
JetClassElementType.getStubType(classKind == ProtoBuf.Class.Kind.ENUM_ENTRY),
|
||||||
|
parent,
|
||||||
|
fqName?.ref(),
|
||||||
|
shortName,
|
||||||
|
superTypeRefs,
|
||||||
|
isTrait = classKind == ProtoBuf.Class.Kind.TRAIT,
|
||||||
|
isEnumEntry = classKind == ProtoBuf.Class.Kind.ENUM_ENTRY,
|
||||||
|
isLocal = false,
|
||||||
|
isTopLevel = classId.isTopLevelClass()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createConstructorStub() {
|
||||||
|
if (!isClass()) return
|
||||||
|
|
||||||
|
val primaryConstructorProto = classProto.getPrimaryConstructor()
|
||||||
|
if (primaryConstructorProto.hasData()) {
|
||||||
|
typeStubBuilder.createValueParameterListStub(classOrObjectStub, primaryConstructorProto.getData(), ProtoContainer(classProto, null))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//default empty constructor
|
||||||
|
KotlinPlaceHolderStubImpl<JetParameterList>(classOrObjectStub, JetStubElementTypes.VALUE_PARAMETER_LIST)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createDelegationSpecifierList() {
|
||||||
|
// if single supertype is any then no delegation specifier list is needed
|
||||||
|
if (supertypeIds.isEmpty()) return
|
||||||
|
|
||||||
|
val delegationSpecifierListStub =
|
||||||
|
KotlinPlaceHolderStubImpl<JetDelegationSpecifierList>(classOrObjectStub, JetStubElementTypes.DELEGATION_SPECIFIER_LIST)
|
||||||
|
|
||||||
|
classProto.getSupertypeList().forEach { type ->
|
||||||
|
val superClassStub = KotlinPlaceHolderStubImpl<JetDelegatorToSuperClass>(
|
||||||
|
delegationSpecifierListStub, JetStubElementTypes.DELEGATOR_SUPER_CLASS
|
||||||
|
)
|
||||||
|
typeStubBuilder.createTypeReferenceStub(superClassStub, type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createClassBodyAndMemberStubs() {
|
||||||
|
val classBody = KotlinPlaceHolderStubImpl<JetClassBody>(classOrObjectStub, JetStubElementTypes.CLASS_BODY)
|
||||||
|
createClassObjectStub(classBody)
|
||||||
|
createEnumEntryStubs(classBody)
|
||||||
|
createCallableMemberStubs(classBody)
|
||||||
|
createInnerAndNestedClasses(classBody)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createClassObjectStub(classBody: KotlinPlaceHolderStubImpl<JetClassBody>) {
|
||||||
|
if (!classProto.hasClassObject() || classKind == ProtoBuf.Class.Kind.OBJECT) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val classObjectId = classId.createNestedClassId(getClassObjectName(classId.getRelativeClassName().shortName()))
|
||||||
|
createNestedClassStub(classBody, classObjectId)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createEnumEntryStubs(classBody: KotlinPlaceHolderStubImpl<JetClassBody>) {
|
||||||
|
classProto.getEnumEntryList().forEach { id ->
|
||||||
|
val name = c.nameResolver.getName(id)
|
||||||
|
KotlinClassStubImpl(
|
||||||
|
JetStubElementTypes.ENUM_ENTRY,
|
||||||
|
classBody,
|
||||||
|
qualifiedName = c.memberFqNameProvider.getMemberFqName(name).ref(),
|
||||||
|
name = name.ref(),
|
||||||
|
superNames = array(),
|
||||||
|
isTrait = false,
|
||||||
|
isEnumEntry = true,
|
||||||
|
isLocal = false,
|
||||||
|
isTopLevel = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createCallableMemberStubs(classBody: KotlinPlaceHolderStubImpl<JetClassBody>) {
|
||||||
|
val container = ProtoContainer(classProto, null)
|
||||||
|
for (callableProto in classProto.getMemberList()) {
|
||||||
|
createCallableStub(classBody, callableProto, c, container)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isClass(): Boolean {
|
||||||
|
return classKind == ProtoBuf.Class.Kind.CLASS ||
|
||||||
|
classKind == ProtoBuf.Class.Kind.ENUM_CLASS ||
|
||||||
|
classKind == ProtoBuf.Class.Kind.ANNOTATION_CLASS
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createInnerAndNestedClasses(classBody: KotlinPlaceHolderStubImpl<JetClassBody>) {
|
||||||
|
classProto.getNestedClassNameList().forEach { id ->
|
||||||
|
val nestedClassId = classId.createNestedClassId(c.nameResolver.getName(id))
|
||||||
|
createNestedClassStub(classBody, nestedClassId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createNestedClassStub(classBody: StubElement<out PsiElement>, nestedClassId: ClassId) {
|
||||||
|
val classData = c.components.classDataFinder.findClassData(nestedClassId)!!
|
||||||
|
createClassStub(classBody, classData.getClassProto(), nestedClassId, c.child(classData.getNameResolver()))
|
||||||
|
}
|
||||||
|
}
|
||||||
+109
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2014 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.jet.plugin.decompiler.stubBuilder
|
||||||
|
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.NameResolver
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.Name
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.FqName
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.ClassDataFinder
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.ProtoBuf
|
||||||
|
import org.jetbrains.jet.lang.resolve.kotlin.KotlinClassFinder
|
||||||
|
import org.jetbrains.jet.lang.resolve.java.resolver.ErrorReporter
|
||||||
|
import org.jetbrains.jet.lang.resolve.kotlin.AbstractBinaryClassAnnotationAndConstantLoader
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.ClassId
|
||||||
|
import org.jetbrains.jet.storage.LockBasedStorageManager
|
||||||
|
import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.SpecialNames
|
||||||
|
|
||||||
|
|
||||||
|
class ClsStubBuilderComponents(
|
||||||
|
val classDataFinder: ClassDataFinder,
|
||||||
|
val annotationLoader: AnnotationLoaderForStubBuilder
|
||||||
|
) {
|
||||||
|
fun createContext(
|
||||||
|
nameResolver: NameResolver,
|
||||||
|
packageFqName: FqName
|
||||||
|
): ClsStubBuilderContext {
|
||||||
|
return ClsStubBuilderContext(this, nameResolver, MemberFqNameProvider(packageFqName), EmptyTypeParameters)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MemberFqNameProvider(val fqName: FqName) {
|
||||||
|
fun getMemberFqName(name: Name): FqName = fqName.child(name)
|
||||||
|
|
||||||
|
fun child(name: Name?): MemberFqNameProvider =
|
||||||
|
if (name == null || SpecialNames.isClassObjectName(name)) this else MemberFqNameProvider(fqName.child(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
trait TypeParameters {
|
||||||
|
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.getId(), nameResolver.getName(it.getName())) }.toMap()
|
||||||
|
|
||||||
|
override fun get(id: Int): Name = typeParametersById[id] ?: parent[id]
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClsStubBuilderContext(
|
||||||
|
val components: ClsStubBuilderComponents,
|
||||||
|
val nameResolver: NameResolver,
|
||||||
|
val memberFqNameProvider: MemberFqNameProvider,
|
||||||
|
val typeParameters: TypeParameters
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun ClsStubBuilderContext.child(typeParameterList: List<ProtoBuf.TypeParameter>, name: Name? = null): ClsStubBuilderContext {
|
||||||
|
return ClsStubBuilderContext(
|
||||||
|
this.components,
|
||||||
|
this.nameResolver,
|
||||||
|
this.memberFqNameProvider.child(name),
|
||||||
|
this.typeParameters.child(nameResolver, typeParameterList)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ClsStubBuilderContext.child(nameResolver: NameResolver): ClsStubBuilderContext {
|
||||||
|
return ClsStubBuilderContext(
|
||||||
|
this.components,
|
||||||
|
nameResolver,
|
||||||
|
this.memberFqNameProvider,
|
||||||
|
this.typeParameters
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
class AnnotationLoaderForStubBuilder(
|
||||||
|
kotlinClassFinder: KotlinClassFinder,
|
||||||
|
errorReporter: ErrorReporter
|
||||||
|
) : AbstractBinaryClassAnnotationAndConstantLoader<ClassId, Unit>(
|
||||||
|
LockBasedStorageManager.NO_LOCKS, kotlinClassFinder, errorReporter) {
|
||||||
|
override fun loadConstant(desc: String, initializer: Any) = null
|
||||||
|
|
||||||
|
override fun loadAnnotation(annotationClassId: ClassId, result: MutableList<ClassId>): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
||||||
|
result.add(annotationClassId)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
+91
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2014 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.jet.plugin.decompiler.stubBuilder
|
||||||
|
|
||||||
|
import com.intellij.psi.compiled.ClsStubBuilder
|
||||||
|
import com.intellij.util.cls.ClsFormatException
|
||||||
|
import com.intellij.util.indexing.FileContent
|
||||||
|
import com.intellij.psi.stubs.PsiFileStub
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import com.intellij.psi.impl.compiled.ClassFileStubBuilder
|
||||||
|
import org.jetbrains.jet.lang.resolve.kotlin.KotlinBinaryClassCache
|
||||||
|
import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.JavaProtoBufUtil
|
||||||
|
import org.jetbrains.jet.lang.psi.JetFile
|
||||||
|
import org.jetbrains.jet.plugin.decompiler.textBuilder.LocalClassFinder
|
||||||
|
import org.jetbrains.jet.plugin.decompiler.textBuilder.LocalClassDataFinder
|
||||||
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
|
import org.jetbrains.jet.plugin.decompiler.textBuilder.LoggingErrorReporter
|
||||||
|
import org.jetbrains.jet.plugin.decompiler.isKotlinInternalCompiledFile
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.FqName
|
||||||
|
|
||||||
|
public class KotlinClsStubBuilder : ClsStubBuilder() {
|
||||||
|
override fun getStubVersion() = ClassFileStubBuilder.STUB_VERSION + 1
|
||||||
|
|
||||||
|
override fun buildFileStub(content: FileContent): PsiFileStub<*>? {
|
||||||
|
val file = content.getFile()
|
||||||
|
|
||||||
|
if (isKotlinInternalCompiledFile(file)) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return doBuildFileStub(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
throws(javaClass<ClsFormatException>())
|
||||||
|
fun doBuildFileStub(file: VirtualFile): PsiFileStub<JetFile>? {
|
||||||
|
val kotlinBinaryClass = KotlinBinaryClassCache.getKotlinBinaryClass(file)
|
||||||
|
val header = kotlinBinaryClass.getClassHeader()
|
||||||
|
val classId = kotlinBinaryClass.getClassId()
|
||||||
|
val packageFqName = classId.getPackageFqName()
|
||||||
|
if (!header.isCompatibleAbiVersion) {
|
||||||
|
return createIncompatibleAbiVersionFileStub(packageFqName)
|
||||||
|
}
|
||||||
|
|
||||||
|
val components = createStubBuilderComponents(file, packageFqName)
|
||||||
|
val annotationData = header.annotationData
|
||||||
|
if (annotationData == null) {
|
||||||
|
LOG.error("Corrupted kotlin header for file ${file.getName()}")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return when (header.kind) {
|
||||||
|
KotlinClassHeader.Kind.PACKAGE_FACADE -> {
|
||||||
|
val packageData = JavaProtoBufUtil.readPackageDataFrom(annotationData)
|
||||||
|
val context = components.createContext(packageData.getNameResolver(), packageFqName)
|
||||||
|
createPackageFacadeFileStub(packageData.getPackageProto(), packageFqName, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
KotlinClassHeader.Kind.CLASS -> {
|
||||||
|
val classData = JavaProtoBufUtil.readClassDataFrom(annotationData)
|
||||||
|
val context = components.createContext(classData.getNameResolver(), packageFqName)
|
||||||
|
createTopLevelClassStub(classId, classData.getClassProto(), context)
|
||||||
|
}
|
||||||
|
else -> throw IllegalStateException("Should have processed " + file.getPath() + " with ${header.kind}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createStubBuilderComponents(file: VirtualFile, packageFqName: FqName): ClsStubBuilderComponents {
|
||||||
|
val localClassFinder = LocalClassFinder(file.getParent()!!, packageFqName)
|
||||||
|
val localClassDataFinder = LocalClassDataFinder(localClassFinder, LOG)
|
||||||
|
val annotationLoader = AnnotationLoaderForStubBuilder(localClassFinder, LoggingErrorReporter(LOG))
|
||||||
|
return ClsStubBuilderComponents(localClassDataFinder, annotationLoader)
|
||||||
|
}
|
||||||
|
|
||||||
|
class object {
|
||||||
|
val LOG = Logger.getInstance(javaClass<KotlinClsStubBuilder>())
|
||||||
|
}
|
||||||
|
}
|
||||||
+239
@@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2014 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.jet.plugin.decompiler.stubBuilder
|
||||||
|
|
||||||
|
import com.intellij.psi.stubs.StubElement
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.ProtoBuf
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.FqName
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinPlaceHolderStubImpl
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinNameReferenceExpressionStubImpl
|
||||||
|
import org.jetbrains.jet.lang.psi.JetTypeReference
|
||||||
|
import org.jetbrains.jet.lexer.JetModifierKeywordToken
|
||||||
|
import org.jetbrains.jet.lexer.JetTokens
|
||||||
|
import org.jetbrains.jet.lang.psi.JetParameterList
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinParameterStubImpl
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.Name
|
||||||
|
import org.jetbrains.jet.lang.psi.JetNullableType
|
||||||
|
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||||
|
import org.jetbrains.jet.lang.psi.JetTypeArgumentList
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinTypeProjectionStubImpl
|
||||||
|
import org.jetbrains.jet.lang.psi.JetFunctionType
|
||||||
|
import org.jetbrains.jet.lang.psi.JetFunctionTypeReceiver
|
||||||
|
import org.jetbrains.jet.utils.addToStdlib.singletonOrEmptyList
|
||||||
|
import org.jetbrains.jet.lang.psi.JetTypeParameterList
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.ProtoBuf.Type
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinTypeParameterStubImpl
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.ProtoBuf.TypeParameter.Variance
|
||||||
|
import org.jetbrains.jet.lang.psi.JetTypeConstraintList
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinTypeConstraintStubImpl
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.ClassId
|
||||||
|
import java.util.ArrayList
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.Flags
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable.CallableKind
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinModifierListStubImpl
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.impl.ModifierMaskUtils
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.descriptors.ProtoContainer
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.KotlinUserTypeStub
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.ProtoBuf.Type.Argument.Projection
|
||||||
|
import org.jetbrains.jet.lang.psi.JetProjectionKind
|
||||||
|
|
||||||
|
class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
|
||||||
|
|
||||||
|
fun createTypeReferenceStub(parent: StubElement<out PsiElement>, typeProto: Type) {
|
||||||
|
val typeReference = KotlinPlaceHolderStubImpl<JetTypeReference>(parent, JetStubElementTypes.TYPE_REFERENCE)
|
||||||
|
createTypeStub(typeReference, typeProto)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createTypeStub(parent: StubElement<out PsiElement>, type: Type) {
|
||||||
|
val isNullable = type.getNullable()
|
||||||
|
val effectiveParent = if (isNullable) KotlinPlaceHolderStubImpl<JetNullableType>(parent, JetStubElementTypes.NULLABLE_TYPE) else parent
|
||||||
|
when (type.getConstructor().getKind()) {
|
||||||
|
Type.Constructor.Kind.CLASS -> {
|
||||||
|
createClassReferenceTypeStub(effectiveParent, type)
|
||||||
|
}
|
||||||
|
Type.Constructor.Kind.TYPE_PARAMETER -> {
|
||||||
|
val typeParameterName = c.typeParameters[type.getConstructor().getId()]
|
||||||
|
createStubForTypeName(ClassId.topLevel(FqName.topLevel(typeParameterName)), effectiveParent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createClassReferenceTypeStub(parent: StubElement<out PsiElement>, type: Type) {
|
||||||
|
val classId = c.nameResolver.getClassId(type.getConstructor().getId())
|
||||||
|
val fqName = classId.asSingleFqName()
|
||||||
|
val isFunctionType = KotlinBuiltIns.isExactFunctionType(fqName)
|
||||||
|
val isExtensionFunctionType = KotlinBuiltIns.isExactExtensionFunctionType(fqName)
|
||||||
|
if (isFunctionType || isExtensionFunctionType) {
|
||||||
|
createFunctionTypeStub(parent, type, isExtensionFunctionType)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val typeStub = createStubForTypeName(classId, parent)
|
||||||
|
val typeArgumentProtoList = type.getArgumentList()
|
||||||
|
createTypeArgumentListStub(typeStub, typeArgumentProtoList)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createTypeArgumentListStub(typeStub: KotlinUserTypeStub, typeArgumentProtoList: List<Type.Argument>) {
|
||||||
|
if (typeArgumentProtoList.isEmpty()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val typeArgumentsListStub = KotlinPlaceHolderStubImpl<JetTypeArgumentList>(typeStub, JetStubElementTypes.TYPE_ARGUMENT_LIST)
|
||||||
|
typeArgumentProtoList.forEach { typeArgumentProto ->
|
||||||
|
val projectionKind = typeArgumentProto.getProjection().toProjectionKind()
|
||||||
|
val typeProjection = KotlinTypeProjectionStubImpl(typeArgumentsListStub, projectionKind.ordinal())
|
||||||
|
val modifierKeywordToken = projectionKind.getToken() as? JetModifierKeywordToken
|
||||||
|
createModifierListStub(typeProjection, modifierKeywordToken.singletonOrEmptyList())
|
||||||
|
createTypeReferenceStub(typeProjection, typeArgumentProto.getType())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Projection.toProjectionKind() = when (this) {
|
||||||
|
Projection.IN -> JetProjectionKind.IN
|
||||||
|
Projection.OUT -> JetProjectionKind.OUT
|
||||||
|
Projection.INV -> JetProjectionKind.NONE
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createFunctionTypeStub(parent: StubElement<out PsiElement>, type: Type, isExtensionFunctionType: Boolean) {
|
||||||
|
val typeArgumentList = type.getArgumentList()
|
||||||
|
val functionType = KotlinPlaceHolderStubImpl<JetFunctionType>(parent, JetStubElementTypes.FUNCTION_TYPE)
|
||||||
|
if (isExtensionFunctionType) {
|
||||||
|
val functionTypeReceiverStub
|
||||||
|
= KotlinPlaceHolderStubImpl<JetFunctionTypeReceiver>(functionType, JetStubElementTypes.FUNCTION_TYPE_RECEIVER)
|
||||||
|
val receiverTypeProto = typeArgumentList.first().getType()
|
||||||
|
createTypeReferenceStub(functionTypeReceiverStub, receiverTypeProto)
|
||||||
|
}
|
||||||
|
|
||||||
|
val parameterList = KotlinPlaceHolderStubImpl<JetParameterList>(functionType, JetStubElementTypes.VALUE_PARAMETER_LIST)
|
||||||
|
val typeArgumentsWithoutReceiverAndReturnType
|
||||||
|
= typeArgumentList.subList(if (isExtensionFunctionType) 1 else 0, typeArgumentList.size - 1)
|
||||||
|
typeArgumentsWithoutReceiverAndReturnType.forEach { argument ->
|
||||||
|
val parameter = KotlinParameterStubImpl(parameterList, fqName = null, name = null, isMutable = false, hasValOrVarNode = false, hasDefaultValue = false)
|
||||||
|
createTypeReferenceStub(parameter, argument.getType())
|
||||||
|
}
|
||||||
|
|
||||||
|
val returnType = typeArgumentList.last().getType()
|
||||||
|
createTypeReferenceStub(functionType, returnType)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createValueParameterListStub(parent: StubElement<out PsiElement>, callableProto: ProtoBuf.Callable, container: ProtoContainer) {
|
||||||
|
val callableKind = Flags.CALLABLE_KIND[callableProto.getFlags()]
|
||||||
|
if (callableKind == CallableKind.VAL || callableKind == CallableKind.VAR) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val parameterListStub = KotlinPlaceHolderStubImpl<JetParameterList>(parent, JetStubElementTypes.VALUE_PARAMETER_LIST)
|
||||||
|
for (valueParameterProto in callableProto.getValueParameterList()) {
|
||||||
|
val name = c.nameResolver.getName(valueParameterProto.getName())
|
||||||
|
val parameterStub = KotlinParameterStubImpl(
|
||||||
|
parameterListStub,
|
||||||
|
name = name.ref(),
|
||||||
|
fqName = null,
|
||||||
|
hasDefaultValue = false,
|
||||||
|
hasValOrVarNode = false,
|
||||||
|
isMutable = false
|
||||||
|
)
|
||||||
|
val isVararg = valueParameterProto.hasVarargElementType()
|
||||||
|
val modifierList = if (isVararg) createModifierListStub(parameterStub, listOf(JetTokens.VARARG_KEYWORD)) else null
|
||||||
|
val parameterAnnotations = c.components.annotationLoader.loadValueParameterAnnotations(
|
||||||
|
container, callableProto, c.nameResolver, callableProto.annotatedCallableKind, valueParameterProto
|
||||||
|
)
|
||||||
|
if (parameterAnnotations.isNotEmpty()) {
|
||||||
|
createAnnotationStubs(parameterAnnotations, modifierList ?: createEmptyModifierList(parameterStub))
|
||||||
|
}
|
||||||
|
|
||||||
|
val typeProto = if (isVararg) valueParameterProto.getVarargElementType() else valueParameterProto.getType()
|
||||||
|
createTypeReferenceStub(parameterStub, typeProto)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createEmptyModifierList(parameterStub: KotlinParameterStubImpl): KotlinModifierListStubImpl {
|
||||||
|
return KotlinModifierListStubImpl(
|
||||||
|
parameterStub,
|
||||||
|
ModifierMaskUtils.computeMask { false },
|
||||||
|
JetStubElementTypes.MODIFIER_LIST
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createTypeParameterListStub(
|
||||||
|
parent: StubElement<out PsiElement>,
|
||||||
|
typeParameterProtoList: List<ProtoBuf.TypeParameter>
|
||||||
|
): List<Pair<Name, Type>> {
|
||||||
|
if (typeParameterProtoList.isEmpty()) return listOf()
|
||||||
|
|
||||||
|
val typeParameterListStub = KotlinPlaceHolderStubImpl<JetTypeParameterList>(parent, JetStubElementTypes.TYPE_PARAMETER_LIST)
|
||||||
|
val protosForTypeConstraintList = arrayListOf<Pair<Name, Type>>()
|
||||||
|
for (proto in typeParameterProtoList) {
|
||||||
|
val name = c.nameResolver.getName(proto.getName())
|
||||||
|
val typeParameterStub = KotlinTypeParameterStubImpl(
|
||||||
|
typeParameterListStub,
|
||||||
|
name = name.ref(),
|
||||||
|
isInVariance = proto.getVariance() == Variance.IN,
|
||||||
|
isOutVariance = proto.getVariance() == Variance.OUT
|
||||||
|
)
|
||||||
|
createTypeParameterModifierListStub(typeParameterStub, proto)
|
||||||
|
val upperBoundProtos = proto.getUpperBoundList()
|
||||||
|
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<JetTypeConstraintList>(parent, JetStubElementTypes.TYPE_CONSTRAINT_LIST)
|
||||||
|
for ((name, type) in protosForTypeConstraintList) {
|
||||||
|
val typeConstraintStub = KotlinTypeConstraintStubImpl(typeConstraintListStub, isClassObjectConstraint = false)
|
||||||
|
KotlinNameReferenceExpressionStubImpl(typeConstraintStub, name.ref())
|
||||||
|
createTypeReferenceStub(typeConstraintStub, type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createTypeParameterModifierListStub(
|
||||||
|
typeParameterStub: KotlinTypeParameterStubImpl,
|
||||||
|
typeParameterProto: ProtoBuf.TypeParameter
|
||||||
|
) {
|
||||||
|
val modifiers = ArrayList<JetModifierKeywordToken>()
|
||||||
|
when (typeParameterProto.getVariance()) {
|
||||||
|
Variance.IN -> modifiers.add(JetTokens.IN_KEYWORD)
|
||||||
|
Variance.OUT -> modifiers.add(JetTokens.OUT_KEYWORD)
|
||||||
|
}
|
||||||
|
if (typeParameterProto.getReified()) {
|
||||||
|
modifiers.add(JetTokens.REIFIED_KEYWORD)
|
||||||
|
}
|
||||||
|
createModifierListStub(typeParameterStub, modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Type.isDefaultUpperBound(): Boolean {
|
||||||
|
val constructor = getConstructor()
|
||||||
|
if (constructor.getKind() != Type.Constructor.Kind.CLASS) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
val classId = c.nameResolver.getClassId(constructor.getId())
|
||||||
|
return KotlinBuiltIns.isAny(classId.asSingleFqName()) && this.getNullable()
|
||||||
|
}
|
||||||
|
}
|
||||||
+204
@@ -0,0 +1,204 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2014 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.jet.plugin.decompiler.stubBuilder
|
||||||
|
|
||||||
|
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.FqName
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinFileStubImpl
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinPlaceHolderStubImpl
|
||||||
|
import org.jetbrains.jet.lang.psi.JetPackageDirective
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes
|
||||||
|
import com.intellij.psi.stubs.StubElement
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinNameReferenceExpressionStubImpl
|
||||||
|
import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.ClassId
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.KotlinUserTypeStub
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.SpecialNames
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinUserTypeStubImpl
|
||||||
|
import org.jetbrains.jet.lexer.JetModifierKeywordToken
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.Flags
|
||||||
|
import org.jetbrains.jet.lexer.JetTokens
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinModifierListStubImpl
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.impl.ModifierMaskUtils
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.ProtoBuf
|
||||||
|
import com.intellij.util.io.StringRef
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.descriptors.ProtoContainer
|
||||||
|
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinAnnotationEntryStubImpl
|
||||||
|
import org.jetbrains.jet.lang.psi.JetConstructorCalleeExpression
|
||||||
|
import org.jetbrains.jet.lang.psi.JetTypeReference
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.Name
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.descriptors.AnnotatedCallableKind
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable.CallableKind
|
||||||
|
|
||||||
|
fun createTopLevelClassStub(classId: ClassId, classProto: ProtoBuf.Class, context: ClsStubBuilderContext): KotlinFileStubImpl {
|
||||||
|
val fileStub = createFileStub(classId.getPackageFqName())
|
||||||
|
createClassStub(fileStub, classProto, classId, context)
|
||||||
|
return fileStub
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createPackageFacadeFileStub(
|
||||||
|
packageProto: ProtoBuf.Package,
|
||||||
|
packageFqName: FqName,
|
||||||
|
c: ClsStubBuilderContext
|
||||||
|
): KotlinFileStubImpl {
|
||||||
|
val fileStub = createFileStub(packageFqName)
|
||||||
|
val container = ProtoContainer(null, packageFqName)
|
||||||
|
for (callableProto in packageProto.getMemberList()) {
|
||||||
|
createCallableStub(fileStub, callableProto, c, container)
|
||||||
|
}
|
||||||
|
return fileStub
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createIncompatibleAbiVersionFileStub(packageFqName: FqName) = createFileStub(packageFqName)
|
||||||
|
|
||||||
|
fun createFileStub(packageFqName: FqName): KotlinFileStubImpl {
|
||||||
|
val fileStub = KotlinFileStubImpl(null, packageFqName.asString(), packageFqName.isRoot())
|
||||||
|
val packageDirectiveStub = KotlinPlaceHolderStubImpl<JetPackageDirective>(fileStub, JetStubElementTypes.PACKAGE_DIRECTIVE)
|
||||||
|
createStubForPackageName(packageDirectiveStub, packageFqName)
|
||||||
|
return fileStub
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createStubForPackageName(packageDirectiveStub: KotlinPlaceHolderStubImpl<JetPackageDirective>, packageFqName: FqName) {
|
||||||
|
val segments = packageFqName.pathSegments().toArrayList()
|
||||||
|
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<JetDotQualifiedExpression>(current, JetStubElementTypes.DOT_QUALIFIED_EXPRESSION)
|
||||||
|
recCreateStubForPackageName(receiver)
|
||||||
|
KotlinNameReferenceExpressionStubImpl(receiver, lastSegment.ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
recCreateStubForPackageName(packageDirectiveStub)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createStubForTypeName(typeClassId: ClassId, parent: StubElement<out PsiElement>): KotlinUserTypeStub {
|
||||||
|
//TODO: should go away with default objects
|
||||||
|
val segments = typeClassId.asSingleFqName().pathSegments().filter { !SpecialNames.isClassObjectName(it) }.toArrayList()
|
||||||
|
assert(segments.isNotEmpty())
|
||||||
|
val iterator = segments.listIterator(segments.size())
|
||||||
|
|
||||||
|
fun recCreateStubForType(current: StubElement<out PsiElement>): KotlinUserTypeStub {
|
||||||
|
val lastSegment = iterator.previous()
|
||||||
|
val userTypeStub = KotlinUserTypeStubImpl(current, isAbsoluteInRootPackage = false)
|
||||||
|
if (iterator.hasPrevious()) {
|
||||||
|
recCreateStubForType(userTypeStub)
|
||||||
|
}
|
||||||
|
KotlinNameReferenceExpressionStubImpl(userTypeStub, lastSegment.ref())
|
||||||
|
return userTypeStub
|
||||||
|
}
|
||||||
|
|
||||||
|
return recCreateStubForType(parent)
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class FlagsToModifiers {
|
||||||
|
MODALITY {
|
||||||
|
override fun getModifiers(flags: Int): JetModifierKeywordToken {
|
||||||
|
val modality = Flags.MODALITY.get(flags)
|
||||||
|
return when (modality) {
|
||||||
|
ProtoBuf.Modality.ABSTRACT -> JetTokens.ABSTRACT_KEYWORD
|
||||||
|
ProtoBuf.Modality.FINAL -> JetTokens.FINAL_KEYWORD
|
||||||
|
ProtoBuf.Modality.OPEN -> JetTokens.OPEN_KEYWORD
|
||||||
|
else -> throw IllegalStateException("Unexpected modality: $modality")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VISIBILITY {
|
||||||
|
override fun getModifiers(flags: Int): JetModifierKeywordToken? {
|
||||||
|
val visibility = Flags.VISIBILITY.get(flags)
|
||||||
|
return when (visibility) {
|
||||||
|
ProtoBuf.Visibility.PRIVATE -> JetTokens.PRIVATE_KEYWORD
|
||||||
|
ProtoBuf.Visibility.INTERNAL -> JetTokens.INTERNAL_KEYWORD
|
||||||
|
ProtoBuf.Visibility.PROTECTED -> JetTokens.PROTECTED_KEYWORD
|
||||||
|
ProtoBuf.Visibility.PUBLIC -> JetTokens.PUBLIC_KEYWORD
|
||||||
|
//TODO: support extra visibility
|
||||||
|
else -> throw IllegalStateException("Unexpected visibility: $visibility")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
INNER {
|
||||||
|
override fun getModifiers(flags: Int): JetModifierKeywordToken? {
|
||||||
|
return if (Flags.INNER.get(flags)) JetTokens.INNER_KEYWORD else null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun getModifiers(flags: Int): JetModifierKeywordToken?
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createModifierListStubForDeclaration(
|
||||||
|
parent: StubElement<out PsiElement>,
|
||||||
|
flags: Int,
|
||||||
|
flagsToTranslate: List<FlagsToModifiers> = listOf(),
|
||||||
|
additionalModifiers: List<JetModifierKeywordToken> = listOf()
|
||||||
|
): KotlinModifierListStubImpl {
|
||||||
|
assert(flagsToTranslate.isNotEmpty())
|
||||||
|
|
||||||
|
val modifiers = flagsToTranslate.map { it.getModifiers(flags) }.filterNotNull() + additionalModifiers
|
||||||
|
return createModifierListStub(parent, modifiers)!!
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createModifierListStub(
|
||||||
|
parent: StubElement<out PsiElement>,
|
||||||
|
modifiers: Collection<JetModifierKeywordToken>
|
||||||
|
): KotlinModifierListStubImpl? {
|
||||||
|
if (modifiers.isEmpty()) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return KotlinModifierListStubImpl(
|
||||||
|
parent,
|
||||||
|
ModifierMaskUtils.computeMask { it in modifiers },
|
||||||
|
JetStubElementTypes.MODIFIER_LIST
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createAnnotationStubs(annotationIds: List<ClassId>, modifierList: KotlinModifierListStubImpl) = annotationIds.forEach {
|
||||||
|
annotationClassId ->
|
||||||
|
val annotationEntryStubImpl = KotlinAnnotationEntryStubImpl(
|
||||||
|
modifierList,
|
||||||
|
shortName = annotationClassId.asSingleFqName().shortName().ref(),
|
||||||
|
hasValueArguments = false
|
||||||
|
)
|
||||||
|
val constructorCallee = KotlinPlaceHolderStubImpl<JetConstructorCalleeExpression>(annotationEntryStubImpl, JetStubElementTypes.CONSTRUCTOR_CALLEE)
|
||||||
|
val typeReference = KotlinPlaceHolderStubImpl<JetTypeReference>(constructorCallee, JetStubElementTypes.TYPE_REFERENCE)
|
||||||
|
createStubForTypeName(annotationClassId, typeReference)
|
||||||
|
}
|
||||||
|
|
||||||
|
val ProtoBuf.Callable.annotatedCallableKind: AnnotatedCallableKind
|
||||||
|
get() {
|
||||||
|
val callableKind = Flags.CALLABLE_KIND[getFlags()]
|
||||||
|
return when (callableKind) {
|
||||||
|
CallableKind.VAL, CallableKind.VAR -> AnnotatedCallableKind.PROPERTY
|
||||||
|
CallableKind.FUN, CallableKind.CONSTRUCTOR -> AnnotatedCallableKind.FUNCTION
|
||||||
|
else -> throw IllegalStateException("Unsupported callable kind: ${callableKind}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Name.ref() = StringRef.fromString(this.asString())
|
||||||
|
|
||||||
|
fun FqName.ref() = StringRef.fromString(this.asString())
|
||||||
Reference in New Issue
Block a user