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

kotlin.reflect.jvm.internal.impl.descriptors.impl.EnumEntrySyntheticClassDescriptor Maven / Gradle / Ivy

/*
 * 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 kotlin.reflect.jvm.internal.impl.descriptors.impl;

import kotlin.jvm.functions.Function0;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import kotlin.reflect.jvm.internal.impl.descriptors.*;
import kotlin.reflect.jvm.internal.impl.descriptors.annotations.Annotations;
import kotlin.reflect.jvm.internal.impl.incremental.components.LookupLocation;
import kotlin.reflect.jvm.internal.impl.incremental.components.NoLookupLocation;
import kotlin.reflect.jvm.internal.impl.name.Name;
import kotlin.reflect.jvm.internal.impl.resolve.DescriptorFactory;
import kotlin.reflect.jvm.internal.impl.resolve.OverridingUtil;
import kotlin.reflect.jvm.internal.impl.resolve.scopes.DescriptorKindFilter;
import kotlin.reflect.jvm.internal.impl.resolve.scopes.MemberScope;
import kotlin.reflect.jvm.internal.impl.resolve.scopes.MemberScopeImpl;
import kotlin.reflect.jvm.internal.impl.resolve.scopes.StaticScopeForKotlinClass;
import kotlin.reflect.jvm.internal.impl.storage.MemoizedFunctionToNotNull;
import kotlin.reflect.jvm.internal.impl.storage.NotNullLazyValue;
import kotlin.reflect.jvm.internal.impl.storage.StorageManager;
import kotlin.reflect.jvm.internal.impl.types.KotlinType;
import kotlin.reflect.jvm.internal.impl.types.TypeConstructor;
import kotlin.reflect.jvm.internal.impl.types.TypeConstructorImpl;
import kotlin.reflect.jvm.internal.impl.utils.Printer;

import java.util.*;

public class EnumEntrySyntheticClassDescriptor extends ClassDescriptorBase {
    private final TypeConstructor typeConstructor;
    private final ConstructorDescriptor primaryConstructor;
    private final MemberScope scope;
    private final MemberScope staticScope = new StaticScopeForKotlinClass(this);
    private final NotNullLazyValue> enumMemberNames;
    private final Annotations annotations;

    /**
     * Creates and initializes descriptors for enum entry with the given name and its companion object
     * @param enumMemberNames needed for fake overrides resolution
     */
    @NotNull
    public static EnumEntrySyntheticClassDescriptor create(
            @NotNull StorageManager storageManager,
            @NotNull ClassDescriptor enumClass,
            @NotNull Name name,
            @NotNull NotNullLazyValue> enumMemberNames,
            @NotNull Annotations annotations,
            @NotNull SourceElement source
    ) {
        KotlinType enumType = enumClass.getDefaultType();

        return new EnumEntrySyntheticClassDescriptor(storageManager, enumClass, enumType, name, enumMemberNames, annotations, source);
    }

    private EnumEntrySyntheticClassDescriptor(
            @NotNull StorageManager storageManager,
            @NotNull ClassDescriptor containingClass,
            @NotNull KotlinType supertype,
            @NotNull Name name,
            @NotNull NotNullLazyValue> enumMemberNames,
            @NotNull Annotations annotations,
            @NotNull SourceElement source
    ) {
        super(storageManager, containingClass, name, source);
        assert containingClass.getKind() == ClassKind.ENUM_CLASS;

        this.annotations = annotations;
        this.typeConstructor =
                TypeConstructorImpl.createForClass(this, getAnnotations(), true, "enum entry", Collections.emptyList(),
                                        Collections.singleton(supertype));

        this.scope = new EnumEntryScope(storageManager);
        this.enumMemberNames = enumMemberNames;

        ConstructorDescriptorImpl primaryConstructor = DescriptorFactory.createPrimaryConstructorForObject(this, source);
        primaryConstructor.setReturnType(getDefaultType());
        this.primaryConstructor = primaryConstructor;
    }

    @NotNull
    @Override
    public MemberScope getUnsubstitutedMemberScope() {
        return scope;
    }

    @NotNull
    @Override
    public MemberScope getStaticScope() {
        return staticScope;
    }

    @NotNull
    @Override
    public Collection getConstructors() {
        return Collections.singleton(primaryConstructor);
    }

    @NotNull
    @Override
    public TypeConstructor getTypeConstructor() {
        return typeConstructor;
    }

    @Nullable
    @Override
    public ClassDescriptor getCompanionObjectDescriptor() {
        return null;
    }

    @NotNull
    @Override
    public ClassKind getKind() {
        return ClassKind.ENUM_ENTRY;
    }

    @NotNull
    @Override
    public Modality getModality() {
        return Modality.FINAL;
    }

    @NotNull
    @Override
    public Visibility getVisibility() {
        return Visibilities.PUBLIC;
    }

    @Override
    public boolean isInner() {
        return false;
    }

    @Override
    public boolean isData() {
        return false;
    }

    @Override
    public boolean isCompanionObject() {
        return false;
    }

    @Nullable
    @Override
    public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
        return primaryConstructor;
    }

    @NotNull
    @Override
    public Annotations getAnnotations() {
        return annotations;
    }

    @Override
    public String toString() {
        return "enum entry " + getName();
    }

    @NotNull
    @Override
    public List getDeclaredTypeParameters() {
        return Collections.emptyList();
    }

    private class EnumEntryScope extends MemberScopeImpl {
        private final MemoizedFunctionToNotNull> functions;
        private final MemoizedFunctionToNotNull> properties;
        private final NotNullLazyValue> allDescriptors;

        public EnumEntryScope(@NotNull StorageManager storageManager) {
            this.functions = storageManager.createMemoizedFunction(new Function1>() {
                @Override
                public Collection invoke(Name name) {
                    return computeFunctions(name);
                }
            });

            this.properties = storageManager.createMemoizedFunction(new Function1>() {
                @Override
                public Collection invoke(Name name) {
                    return computeProperties(name);
                }
            });
            this.allDescriptors = storageManager.createLazyValue(new Function0>() {
                @Override
                public Collection invoke() {
                    return computeAllDeclarations();
                }
            });
        }

        @NotNull
        @Override
        @SuppressWarnings({"unchecked"}) // KT-9898 Impossible implement kotlin interface in java
        public Collection getContributedVariables(@NotNull Name name, @NotNull LookupLocation location) {
            return properties.invoke(name);
        }

        @NotNull
        @SuppressWarnings("unchecked")
        private Collection computeProperties(@NotNull Name name) {
            return resolveFakeOverrides(name, (Collection) getSupertypeScope().getContributedVariables(name, NoLookupLocation.FOR_NON_TRACKED_SCOPE));
        }

        @NotNull
        @Override
        public Collection getContributedFunctions(@NotNull Name name, @NotNull LookupLocation location) {
            return functions.invoke(name);
        }

        @NotNull
        private Collection computeFunctions(@NotNull Name name) {
            return resolveFakeOverrides(name, getSupertypeScope().getContributedFunctions(name, NoLookupLocation.FOR_NON_TRACKED_SCOPE));
        }

        @NotNull
        private MemberScope getSupertypeScope() {
            Collection supertype = getTypeConstructor().getSupertypes();
            assert supertype.size() == 1 : "Enum entry and its companion object both should have exactly one supertype: " + supertype;
            return supertype.iterator().next().getMemberScope();
        }

        @NotNull
        private  Collection resolveFakeOverrides(
                @NotNull Name name,
                @NotNull Collection fromSupertypes
        ) {
            final Set result = new LinkedHashSet();

            OverridingUtil.generateOverridesInFunctionGroup(
                    name, fromSupertypes, Collections.emptySet(), EnumEntrySyntheticClassDescriptor.this,
                    new OverridingUtil.DescriptorSink() {
                        @Override
                        @SuppressWarnings("unchecked")
                        public void addFakeOverride(@NotNull CallableMemberDescriptor fakeOverride) {
                            OverridingUtil.resolveUnknownVisibilityForMember(fakeOverride, null);
                            result.add((D) fakeOverride);
                        }

                        @Override
                        public void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent) {
                            // Do nothing
                        }
                    }
            );

            return result;
        }

        @NotNull
        @Override
        public Collection getContributedDescriptors(
                @NotNull DescriptorKindFilter kindFilter,
                @NotNull Function1 nameFilter
        ) {
            return allDescriptors.invoke();
        }

        @NotNull
        private Collection computeAllDeclarations() {
            Collection result = new HashSet();
            for (Name name : enumMemberNames.invoke()) {
                result.addAll(getContributedFunctions(name, NoLookupLocation.FOR_NON_TRACKED_SCOPE));
                result.addAll(getContributedVariables(name, NoLookupLocation.FOR_NON_TRACKED_SCOPE));
            }
            return result;
        }

        @Override
        public void printScopeStructure(@NotNull Printer p) {
            p.println("enum entry scope for " + EnumEntrySyntheticClassDescriptor.this);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy