From c78410855df066a25c7452d7e3111de08ae651dc Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Sun, 11 Oct 2015 16:39:55 +0300 Subject: [PATCH] Refactor CallableClsStubBuilder, separate functions and properties --- .../stubBuilder/CallableClsStubBuilder.kt | 238 +++++++++--------- 1 file changed, 121 insertions(+), 117 deletions(-) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/CallableClsStubBuilder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/CallableClsStubBuilder.kt index 6f977e9cb95..5635d76448d 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/CallableClsStubBuilder.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/CallableClsStubBuilder.kt @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.idea.decompiler.stubBuilder -import com.google.protobuf.MessageLite import com.intellij.psi.PsiElement import com.intellij.psi.stubs.StubElement import org.jetbrains.kotlin.idea.decompiler.stubBuilder.FlagsToModifiers.* @@ -42,12 +41,12 @@ fun createCallableStubs( ) { for (propertyProto in propertyProtos) { if (!shouldSkip(propertyProto.flags, outerContext.nameResolver.getName(propertyProto.name))) { - CallableClsStubBuilder(parentStub, propertyProto, outerContext, protoContainer).build() + PropertyClsStubBuilder(parentStub, outerContext, protoContainer, propertyProto).build() } } for (functionProto in functionProtos) { if (!shouldSkip(functionProto.flags, outerContext.nameResolver.getName(functionProto.name))) { - CallableClsStubBuilder(parentStub, functionProto, outerContext, protoContainer).build() + FunctionClsStubBuilder(parentStub, outerContext, protoContainer, functionProto).build() } } } @@ -58,7 +57,7 @@ fun createConstructorStub( outerContext: ClsStubBuilderContext, protoContainer: ProtoContainer ) { - ConstructorClsStubBuilder(parentStub, constructorProto, outerContext, protoContainer).build() + ConstructorClsStubBuilder(parentStub, outerContext, protoContainer, constructorProto).build() } private fun shouldSkip(flags: Int, name: Name): Boolean { @@ -70,155 +69,160 @@ private fun shouldSkip(flags: Int, name: Name): Boolean { } } -private class CallableClsStubBuilder private constructor( - private val parent: StubElement, - private val callableProto: MessageLite, +abstract class CallableClsStubBuilder( + parent: StubElement, outerContext: ClsStubBuilderContext, - private val protoContainer: ProtoContainer, - private val callableKind: CallableClsStubBuilder.CallableKind, - private val nameIndex: Int, - private val typeParameterList: List, - private val valueParameterList: List, - private val receiverType: ProtoBuf.Type?, - private val returnType: ProtoBuf.Type?, - private val flags: Int + protected val protoContainer: ProtoContainer, + private val typeParameters: List ) { - private val c = outerContext.child(typeParameterList) - private val typeStubBuilder = TypeClsStubBuilder(c) - private val isTopLevel: Boolean get() = protoContainer.packageFqName != null - private val callableStub = doCreateCallableStub() - - enum class CallableKind { - FUN, VAL, VAR - } - - constructor( - parent: StubElement, - functionProto: ProtoBuf.Function, - outerContext: ClsStubBuilderContext, - protoContainer: ProtoContainer - ) : this( - parent, functionProto, outerContext, protoContainer, CallableKind.FUN, - functionProto.name, functionProto.typeParameterList, functionProto.valueParameterList, - if (functionProto.hasReceiverType()) functionProto.receiverType else null, - if (functionProto.hasReturnType()) functionProto.returnType else null, - functionProto.flags - ) - - constructor( - parent: StubElement, - propertyProto: ProtoBuf.Property, - outerContext: ClsStubBuilderContext, - protoContainer: ProtoContainer - ) : this( - parent, propertyProto, outerContext, protoContainer, - if (Flags.IS_VAR.get(propertyProto.flags)) CallableKind.VAR else CallableKind.VAL, - propertyProto.name, propertyProto.typeParameterList, emptyList(), - if (propertyProto.hasReceiverType()) propertyProto.receiverType else null, - if (propertyProto.hasReturnType()) propertyProto.returnType else null, - propertyProto.flags - ) + protected val c = outerContext.child(typeParameters) + protected val typeStubBuilder = TypeClsStubBuilder(c) + protected val isTopLevel: Boolean get() = protoContainer.packageFqName != null + protected val callableStub: StubElement by lazy(LazyThreadSafetyMode.NONE) { doCreateCallableStub(parent) } fun build() { createModifierListStub() - val typeConstraintListData = typeStubBuilder.createTypeParameterListStub(callableStub, typeParameterList) + val typeConstraintListData = typeStubBuilder.createTypeParameterListStub(callableStub, typeParameters) createReceiverTypeReferenceStub() createValueParameterList() createReturnTypeStub() typeStubBuilder.createTypeConstraintListStub(callableStub, typeConstraintListData) } - private fun createValueParameterList() { - if (callableKind == CallableKind.FUN) { - typeStubBuilder.createValueParameterListStub(callableStub, callableProto, valueParameterList, protoContainer) - } - } + abstract val receiverType: ProtoBuf.Type? + abstract val returnType: ProtoBuf.Type? private fun createReceiverTypeReferenceStub() { - if (receiverType != null) { - typeStubBuilder.createTypeReferenceStub(callableStub, receiverType) + receiverType?.let { + typeStubBuilder.createTypeReferenceStub(callableStub, it) } } private fun createReturnTypeStub() { - if (returnType != null) { - typeStubBuilder.createTypeReferenceStub(callableStub, returnType) + returnType?.let { + typeStubBuilder.createTypeReferenceStub(callableStub, it) } } - private fun createModifierListStub() { - val modalityModifiers = if (isTopLevel) listOf() else listOf(MODALITY) - val constModifiers = if (callableKind == CallableKind.VAL) listOf(CONST) else listOf() + abstract fun createModifierListStub() - val additionalModifiers = when (callableKind) { - CallableKind.FUN -> arrayOf(OPERATOR, INFIX) - CallableKind.VAL, CallableKind.VAR -> arrayOf(LATEINIT) - else -> emptyArray() - } + abstract fun createValueParameterList() - val relevantModifiers = listOf(VISIBILITY) + constModifiers + modalityModifiers + additionalModifiers - val modifierListStubImpl = createModifierListStubForDeclaration(callableStub, flags, relevantModifiers) + abstract fun doCreateCallableStub(parent: StubElement): StubElement +} - val kind = callableProto.annotatedCallableKind - val annotationIds = c.components.annotationLoader.loadCallableAnnotations(protoContainer, callableProto, kind) +private class FunctionClsStubBuilder( + parent: StubElement, + outerContext: ClsStubBuilderContext, + protoContainer: ProtoContainer, + private val functionProto: ProtoBuf.Function +) : CallableClsStubBuilder(parent, outerContext, protoContainer, functionProto.typeParameterList) { + override val receiverType: ProtoBuf.Type? + get() = if (functionProto.hasReceiverType()) functionProto.receiverType else null + + override val returnType: ProtoBuf.Type? + get() = if (functionProto.hasReturnType()) functionProto.returnType else null + + override fun createValueParameterList() { + typeStubBuilder.createValueParameterListStub(callableStub, functionProto, functionProto.valueParameterList, protoContainer) + } + + override fun createModifierListStub() { + val modalityModifier = if (isTopLevel) listOf() else listOf(MODALITY) + val modifierListStubImpl = createModifierListStubForDeclaration( + callableStub, functionProto.flags, + listOf(VISIBILITY, OPERATOR, INFIX) + modalityModifier + ) + + val annotationIds = c.components.annotationLoader.loadCallableAnnotations( + protoContainer, functionProto, AnnotatedCallableKind.FUNCTION + ) createTargetedAnnotationStubs(annotationIds, modifierListStubImpl) } - private fun doCreateCallableStub(): StubElement { - val callableName = c.nameResolver.getName(nameIndex) + override fun doCreateCallableStub(parent: StubElement): StubElement { + val callableName = c.nameResolver.getName(functionProto.name) - return when (callableKind) { - CallableKind.FUN -> { - KotlinFunctionStubImpl( - parent, - callableName.ref(), - isTopLevel, - c.containerFqName.child(callableName), - isExtension = receiverType != null, - hasBlockBody = true, - hasBody = Flags.MODALITY.get(flags) != Modality.ABSTRACT, - hasTypeParameterListBeforeFunctionName = typeParameterList.isNotEmpty() - ) - } - CallableKind.VAL, CallableKind.VAR -> { - KotlinPropertyStubImpl( - parent, - callableName.ref(), - isVar = callableKind == CallableKind.VAR, - isTopLevel = isTopLevel, - hasDelegate = false, - hasDelegateExpression = false, - hasInitializer = false, - isExtension = receiverType != null, - hasReturnTypeRef = true, - fqName = c.containerFqName.child(callableName) - ) - } - else -> throw IllegalStateException("Unknown callable kind $callableKind") - } + return KotlinFunctionStubImpl( + parent, + callableName.ref(), + isTopLevel, + c.containerFqName.child(callableName), + isExtension = functionProto.hasReceiverType(), + hasBlockBody = true, + hasBody = Flags.MODALITY.get(functionProto.flags) != Modality.ABSTRACT, + hasTypeParameterListBeforeFunctionName = functionProto.typeParameterList.isNotEmpty() + ) + } +} + +private class PropertyClsStubBuilder( + parent: StubElement, + outerContext: ClsStubBuilderContext, + protoContainer: ProtoContainer, + private val propertyProto: ProtoBuf.Property +) : CallableClsStubBuilder(parent, outerContext, protoContainer, propertyProto.typeParameterList) { + private val isVar = Flags.IS_VAR.get(propertyProto.flags) + + override val receiverType: ProtoBuf.Type? + get() = if (propertyProto.hasReceiverType()) propertyProto.receiverType else null + + override val returnType: ProtoBuf.Type? + get() = if (propertyProto.hasReturnType()) propertyProto.returnType else null + + override fun createValueParameterList() { + } + + override fun createModifierListStub() { + val constModifier = if (isVar) listOf() else listOf(CONST) + val modalityModifier = if (isTopLevel) listOf() else listOf(MODALITY) + + val modifierListStubImpl = createModifierListStubForDeclaration( + callableStub, propertyProto.flags, + listOf(VISIBILITY, LATEINIT) + constModifier + modalityModifier + ) + + val annotationIds = c.components.annotationLoader.loadCallableAnnotations( + protoContainer, propertyProto, AnnotatedCallableKind.PROPERTY + ) + createTargetedAnnotationStubs(annotationIds, modifierListStubImpl) + } + + override fun doCreateCallableStub(parent: StubElement): StubElement { + val callableName = c.nameResolver.getName(propertyProto.name) + + return KotlinPropertyStubImpl( + parent, + callableName.ref(), + isVar, + isTopLevel, + hasDelegate = false, + hasDelegateExpression = false, + hasInitializer = false, + isExtension = propertyProto.hasReceiverType(), + hasReturnTypeRef = true, + fqName = c.containerFqName.child(callableName) + ) } } private class ConstructorClsStubBuilder( - private val parent: StubElement, - private val constructorProto: ProtoBuf.Constructor, + parent: StubElement, outerContext: ClsStubBuilderContext, - private val protoContainer: ProtoContainer -) { - private val c = outerContext.child(emptyList()) - private val typeStubBuilder = TypeClsStubBuilder(c) - private val callableStub = doCreateCallableStub() + protoContainer: ProtoContainer, + private val constructorProto: ProtoBuf.Constructor +) : CallableClsStubBuilder(parent, outerContext, protoContainer, emptyList()) { + override val receiverType: ProtoBuf.Type? + get() = null - fun build() { - createModifierListStub() - createValueParameterList() - } + override val returnType: ProtoBuf.Type? + get() = null - private fun createValueParameterList() { + override fun createValueParameterList() { typeStubBuilder.createValueParameterListStub(callableStub, constructorProto, constructorProto.valueParameterList, protoContainer) } - private fun createModifierListStub() { + override fun createModifierListStub() { val modifierListStubImpl = createModifierListStubForDeclaration(callableStub, constructorProto.flags, listOf(VISIBILITY)) val annotationIds = c.components.annotationLoader.loadCallableAnnotations( @@ -227,7 +231,7 @@ private class ConstructorClsStubBuilder( createTargetedAnnotationStubs(annotationIds, modifierListStubImpl) } - private fun doCreateCallableStub(): StubElement { + override fun doCreateCallableStub(parent: StubElement): StubElement { return if (Flags.IS_SECONDARY.get(constructorProto.flags)) KotlinPlaceHolderStubImpl(parent, JetStubElementTypes.SECONDARY_CONSTRUCTOR) else