All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.codegen.DelegationFieldsInfo Maven / Gradle / Ivy

There is a newer version: 2.1.0-RC
Show newest version
/*
 * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
 * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
 */

package org.jetbrains.kotlin.codegen;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.CodegenUtil;
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry;
import org.jetbrains.kotlin.psi.KtExpression;
import org.jetbrains.kotlin.psi.KtSuperTypeListEntry;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.org.objectweb.asm.Type;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.jetbrains.kotlin.load.java.JvmAbi.DELEGATE_SUPER_FIELD_PREFIX;

public class DelegationFieldsInfo {
    private final Type classAsmType;
    private final ClassDescriptor classDescriptor;
    private final GenerationState state;
    private final KotlinTypeMapper typeMapper;
    private final BindingContext bindingContext;

    public DelegationFieldsInfo(
            @NotNull Type type,
            @NotNull ClassDescriptor descriptor,
            @NotNull GenerationState state,
            @NotNull BindingContext context
    ) {
        this.classAsmType = type;
        this.classDescriptor = descriptor;
        this.state = state;
        this.typeMapper = state.getTypeMapper();
        this.bindingContext = context;
    }

    public class Field {
        public final Type type;
        public final String name;
        public final boolean generateField;
        public final String genericSignature;

        private Field(Type type, String name, boolean generateField, String genericSignature) {
            this.type = type;
            this.name = name;
            this.generateField = generateField;
            this.genericSignature = genericSignature;
        }

        private Field(Type type, String name, boolean generateField) {
            this(type, name, generateField, null);
        }

        @NotNull
        public StackValue getStackValue() {
            return StackValue.field(type, classAsmType, name, false, StackValue.none());
        }
    }
    private final Map fields = new HashMap<>();

    @Nullable
    public DelegationFieldsInfo.Field getInfo(KtDelegatedSuperTypeEntry specifier) {
        DelegationFieldsInfo.Field field = fields.get(specifier);
        assert field != null || state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES : "No field for " + specifier.getText();
        return field;
    }

    private void addField(KtDelegatedSuperTypeEntry specifier, PropertyDescriptor propertyDescriptor) {
        fields.put(specifier,
                   new DelegationFieldsInfo.Field(typeMapper.mapType(propertyDescriptor), propertyDescriptor.getName().asString(), false));
    }

    private void addField(KtDelegatedSuperTypeEntry specifier, Type type, String name, String genericSignature) {
        fields.put(specifier, new DelegationFieldsInfo.Field(type, name, true, genericSignature));
    }

    @NotNull
    public DelegationFieldsInfo getDelegationFieldsInfo(@NotNull List delegationSpecifiers) {
        DelegationFieldsInfo result = new DelegationFieldsInfo(classAsmType, classDescriptor, state, bindingContext);
        int n = 0;
        for (KtSuperTypeListEntry specifier : delegationSpecifiers) {
            if (specifier instanceof KtDelegatedSuperTypeEntry) {
                KtExpression expression = ((KtDelegatedSuperTypeEntry) specifier).getDelegateExpression();
                if (expression == null) continue;

                PropertyDescriptor propertyDescriptor = CodegenUtil.getDelegatePropertyIfAny(expression, classDescriptor, bindingContext);


                if (CodegenUtil.isFinalPropertyWithBackingField(propertyDescriptor, bindingContext)) {
                    result.addField((KtDelegatedSuperTypeEntry) specifier, propertyDescriptor);
                }
                else {
                    KotlinType expressionType = bindingContext.getType(expression);
                    ClassDescriptor superClass = JvmCodegenUtil.getSuperClass(specifier, state, bindingContext);
                    BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.TYPE);
                    Type asmType =
                            expressionType != null ? typeMapper.mapType(expressionType, sw) :
                            superClass != null ? typeMapper.mapType(superClass.getDefaultType(), sw) : null;

                    if (asmType == null) continue;

                    String genericSignature = sw.makeJavaGenericSignature();
                    result.addField((KtDelegatedSuperTypeEntry) specifier, asmType, DELEGATE_SUPER_FIELD_PREFIX + n, genericSignature);
                }
                n++;
            }
        }
        return result;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy