org.jetbrains.kotlin.codegen.MultifileClassPartCodegen.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-compiler-embeddable Show documentation
Show all versions of kotlin-compiler-embeddable Show documentation
the Kotlin compiler embeddable
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen
import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.backend.common.CodegenUtil
import org.jetbrains.kotlin.codegen.context.MultifileClassPartContext
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.METADATA_PACKAGE_NAME_FIELD_NAME
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
import org.jetbrains.org.objectweb.asm.Opcodes
class MultifileClassPartCodegen(
v: ClassBuilder,
file: KtFile,
private val packageFragment: PackageFragmentDescriptor,
private val superClassInternalName: String,
private val shouldGeneratePartHierarchy: Boolean,
partContext: MultifileClassPartContext,
state: GenerationState
) : MemberCodegen(state, null, partContext, file, v) {
private val partType = partContext.filePartType
private val facadeClassType = partContext.multifileClassType
init {
if (shouldGeneratePartHierarchy && file.declarations.any { it is KtProperty && shouldInitializeProperty(it) }) {
throw AssertionError("State is not allowed in multi-file classes with -Xmultifile-parts-inherit")
}
}
override fun generate() {
if (!state.classBuilderMode.generateMultiFileFacadePartClasses) return
super.generate()
val generateBodies = state.classBuilderMode.generateBodies
if (shouldGeneratePartHierarchy) {
v.newMethod(OtherOrigin(packageFragment), Opcodes.ACC_PUBLIC, "", "()V", null, null).apply {
if (generateBodies) {
visitCode()
visitVarInsn(Opcodes.ALOAD, 0)
visitMethodInsn(Opcodes.INVOKESPECIAL, superClassInternalName, "", "()V", false)
visitInsn(Opcodes.RETURN)
visitMaxs(1, 1)
}
visitEnd()
}
}
}
override fun generateDeclaration() {
val access = if (shouldGeneratePartHierarchy) 0 else Opcodes.ACC_SYNTHETIC or Opcodes.ACC_FINAL
v.defineClass(
element, state.config.classFileVersion, access or Opcodes.ACC_SUPER, partType.internalName, null, superClassInternalName,
ArrayUtil.EMPTY_STRING_ARRAY
)
v.visitSource(element.name, null)
generatePropertyMetadataArrayFieldIfNeeded(partType)
}
override fun generateBody() {
for (declaration in CodegenUtil.getMemberDeclarationsToGenerate(element)) {
genSimpleMember(declaration)
}
if (state.classBuilderMode.generateBodies) {
generateInitializers { createOrGetClInitCodegen() }
}
}
override fun generateKotlinMetadataAnnotation() {
val (serializer, packageProto) = PackagePartCodegen.serializePackagePartMembers(this, partType)
val extraFlags = if (shouldGeneratePartHierarchy) JvmAnnotationNames.METADATA_MULTIFILE_PARTS_INHERIT_FLAG else 0
writeKotlinMetadata(v, state.config, KotlinClassHeader.Kind.MULTIFILE_CLASS_PART, false, extraFlags) { av ->
DescriptorAsmUtil.writeAnnotationData(av, serializer, packageProto)
av.visit(JvmAnnotationNames.METADATA_MULTIFILE_CLASS_NAME_FIELD_NAME, facadeClassType.internalName)
val kotlinPackageFqName = element.packageFqName
if (kotlinPackageFqName != JvmClassName.byInternalName(partType.internalName).packageFqName) {
av.visit(METADATA_PACKAGE_NAME_FIELD_NAME, kotlinPackageFqName.asString())
}
}
}
override fun generateSyntheticPartsAfterBody() {
generateSyntheticAccessors()
}
}