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);
|
||||
}
|
||||
|
||||
private static JetClassElementType getStubType(boolean isEnumEntry) {
|
||||
public static JetClassElementType getStubType(boolean isEnumEntry) {
|
||||
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.ClsStubBuilder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.plugin.decompiler.stubBuilder.KotlinClsStubBuilder;
|
||||
|
||||
public class JetClassFileDecompiler extends ClassFileDecompilers.Full {
|
||||
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