org.jetbrains.kotlin.codegen.ClassBodyCodegen 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 org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.bridges.ImplKt;
import org.jetbrains.kotlin.codegen.context.ClassContext;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.synthetics.SyntheticClassOrObjectDescriptor;
import org.jetbrains.kotlin.psi.synthetics.SyntheticClassOrObjectDescriptorKt;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
public abstract class ClassBodyCodegen extends MemberCodegen {
public final KtPureClassOrObject myClass;
public final OwnerKind kind;
public final ClassDescriptor descriptor;
protected ClassBodyCodegen(
@NotNull KtPureClassOrObject myClass,
@NotNull ClassContext context,
@NotNull ClassBuilder v,
@NotNull GenerationState state,
@Nullable MemberCodegen parentCodegen
) {
super(state, parentCodegen, context, myClass, v);
this.myClass = myClass;
this.kind = context.getContextKind();
this.descriptor = SyntheticClassOrObjectDescriptorKt.findClassDescriptor(myClass, bindingContext);
}
@Override
protected void generateBody() {
List companions = new ArrayList();
if (kind != OwnerKind.DEFAULT_IMPLS) {
//generate nested classes first and only then generate class body. It necessary to access to nested CodegenContexts
for (KtDeclaration declaration : myClass.getDeclarations()) {
if (shouldProcessFirst(declaration)) {
//Generate companions after class body generation (need to record all synthetic accessors)
if (declaration instanceof KtObjectDeclaration && ((KtObjectDeclaration) declaration).isCompanion()) {
companions.add((KtObjectDeclaration) declaration);
CodegenUtilKt.populateCompanionBackingFieldNamesToOuterContextIfNeeded((KtObjectDeclaration) declaration, context, state);
}
else {
generateDeclaration(declaration);
}
}
}
}
for (KtDeclaration declaration : myClass.getDeclarations()) {
if (!shouldProcessFirst(declaration)) {
generateDeclaration(declaration);
}
}
generatePrimaryConstructorProperties();
generateConstructors();
generateDefaultImplsIfNeeded();
// Generate _declared_ companions
for (KtObjectDeclaration companion : companions) {
genClassOrObject(companion);
}
// Generate synthetic (non-declared) companion if needed
ClassDescriptor companionObjectDescriptor = descriptor.getCompanionObjectDescriptor();
if (companionObjectDescriptor instanceof SyntheticClassOrObjectDescriptor) {
genSyntheticClassOrObject((SyntheticClassOrObjectDescriptor) companionObjectDescriptor);
}
if (!DescriptorUtils.isInterface(descriptor)) {
for (DeclarationDescriptor memberDescriptor : DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().getMemberScope())) {
if (memberDescriptor instanceof CallableMemberDescriptor) {
CallableMemberDescriptor member = (CallableMemberDescriptor) memberDescriptor;
if (!member.getKind().isReal() && ImplKt.findInterfaceImplementation(member) == null) {
if (member instanceof FunctionDescriptor) {
functionCodegen.generateBridges((FunctionDescriptor) member);
}
else if (member instanceof PropertyDescriptor) {
PropertyGetterDescriptor getter = ((PropertyDescriptor) member).getGetter();
if (getter != null) {
functionCodegen.generateBridges(getter);
}
PropertySetterDescriptor setter = ((PropertyDescriptor) member).getSetter();
if (setter != null) {
functionCodegen.generateBridges(setter);
}
}
}
}
}
}
}
protected void generateConstructors() {
}
protected void generateDefaultImplsIfNeeded() {
}
private static boolean shouldProcessFirst(KtDeclaration declaration) {
return !(declaration instanceof KtProperty || declaration instanceof KtNamedFunction);
}
protected void generateDeclaration(KtDeclaration declaration) {
if (declaration instanceof KtProperty || declaration instanceof KtNamedFunction || declaration instanceof KtTypeAlias) {
genSimpleMember(declaration);
}
else if (declaration instanceof KtClassOrObject) {
if (declaration instanceof KtEnumEntry && !enumEntryNeedSubclass(bindingContext, (KtEnumEntry) declaration)) {
return;
}
genClassOrObject((KtClassOrObject) declaration);
}
}
private void generatePrimaryConstructorProperties() {
boolean isAnnotation = descriptor.getKind() == ClassKind.ANNOTATION_CLASS;
for (KtParameter p : getPrimaryConstructorParameters()) {
if (p.hasValOrVar()) {
PropertyDescriptor propertyDescriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
if (propertyDescriptor != null) {
if (!isAnnotation) {
propertyCodegen.generatePrimaryConstructorProperty(p, propertyDescriptor);
}
else {
propertyCodegen.generateConstructorPropertyAsMethodForAnnotationClass(p, propertyDescriptor);
}
}
}
}
}
@NotNull
protected List getPrimaryConstructorParameters() {
if (myClass instanceof KtClass) {
return myClass.getPrimaryConstructorParameters();
}
return Collections.emptyList();
}
@Nullable
@Override
protected ClassDescriptor classForInnerClassRecord() {
return DescriptorUtils.isTopLevelDeclaration(descriptor) ? null : descriptor;
}
}