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

org.jetbrains.kotlin.types.ErrorUtils Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
/*
 * Copyright 2010-2016 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.types;

import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.DefaultBuiltIns;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl;
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl;
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl;
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl;
import org.jetbrains.kotlin.incremental.components.LookupLocation;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.platform.TargetPlatform;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter;
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
import org.jetbrains.kotlin.storage.LockBasedStorageManager;
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner;
import org.jetbrains.kotlin.types.error.ErrorSimpleFunctionDescriptorImpl;
import org.jetbrains.kotlin.types.refinement.TypeRefinement;
import org.jetbrains.kotlin.utils.Printer;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import static java.util.Collections.emptySet;
import static kotlin.collections.CollectionsKt.emptyList;

public class ErrorUtils {
    private static final ModuleDescriptor ERROR_MODULE;

    static {
        ERROR_MODULE = new ModuleDescriptor() {
            @Nullable
            @Override
            public  T getCapability(@NotNull ModuleCapability capability) {
                return null;
            }

            @NotNull
            @Override
            public Annotations getAnnotations() {
                return Annotations.Companion.getEMPTY();
            }

            @NotNull
            @Override
            public Collection getSubPackagesOf(@NotNull FqName fqName, @NotNull Function1 nameFilter) {
                return emptyList();
            }

            @NotNull
            @Override
            public Name getName() {
                return Name.special("");
            }

            @NotNull
            @Override
            public Name getStableName() {
                return Name.special("");
            }

            @Nullable
            @Override
            public TargetPlatform getPlatform() {
                return null;
            }

            @NotNull
            @Override
            public PackageViewDescriptor getPackage(@NotNull FqName fqName) {
                throw new IllegalStateException("Should not be called!");
            }

            @NotNull
            @Override
            public List getAllDependencyModules() {
                return emptyList();
            }

            @NotNull
            @Override
            public List getExpectedByModules() {
                return emptyList();
            }

            @Override
            public  R accept(@NotNull DeclarationDescriptorVisitor visitor, D data) {
                return null;
            }

            @Override
            public void acceptVoid(DeclarationDescriptorVisitor visitor) {
            }

            @Override
            public boolean shouldSeeInternalsOf(@NotNull ModuleDescriptor targetModule) {
                return false;
            }

            @NotNull
            @Override
            public DeclarationDescriptor getOriginal() {
                return this;
            }

            @Nullable
            @Override
            public DeclarationDescriptor getContainingDeclaration() {
                return null;
            }

            @NotNull
            @Override
            public KotlinBuiltIns getBuiltIns() {
                return DefaultBuiltIns.getInstance();
            }

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

            @Override
            public void assertValid() {
                throw new InvalidModuleException("ERROR_MODULE is not a valid module");
            }
        };
    }

    /**
     * @return true iff any of the types referenced in parameter types (including type parameters and extension receiver) of the function
     * is an error type. Does not check the return type of the function.
     */
    public static boolean containsErrorTypeInParameters(@NotNull FunctionDescriptor function) {
        ReceiverParameterDescriptor receiverParameter = function.getExtensionReceiverParameter();
        if (receiverParameter != null && containsErrorType(receiverParameter.getType())) {
            return true;
        }
        for (ValueParameterDescriptor parameter : function.getValueParameters()) {
            if (containsErrorType(parameter.getType())) {
                return true;
            }
        }
        for (TypeParameterDescriptor parameter : function.getTypeParameters()) {
            for (KotlinType upperBound : parameter.getUpperBounds()) {
                if (containsErrorType(upperBound)) {
                    return true;
                }
            }
        }

        return false;
    }

    public static class ErrorScope implements MemberScope {
        private final String debugMessage;

        private ErrorScope(@NotNull String debugMessage) {
            this.debugMessage = debugMessage;
        }

        @Nullable
        @Override
        public ClassifierDescriptor getContributedClassifier(@NotNull Name name, @NotNull LookupLocation location) {
            return createErrorClass(name.asString());
        }

        @Nullable
        @Override
        public DescriptorWithDeprecation getContributedClassifierIncludeDeprecated(
                @NotNull Name name, @NotNull LookupLocation location
        ) {
            return null;
        }

        @NotNull
        @Override
        public Set getContributedVariables(@NotNull Name name, @NotNull LookupLocation location) {
            return ERROR_PROPERTY_GROUP;
        }

        @NotNull
        @Override
        public Set getContributedFunctions(@NotNull Name name, @NotNull LookupLocation location) {
            return Collections.singleton(createErrorFunction(this));
        }

        @NotNull
        @Override
        public Set getFunctionNames() {
            return emptySet();
        }

        @NotNull
        @Override
        public Set getVariableNames() {
            return emptySet();
        }

        @NotNull
        @Override
        public Set getClassifierNames() {
            return emptySet();
        }

        @Override
        public void recordLookup(@NotNull Name name, @NotNull LookupLocation location) {

        }

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

        @Override
        public boolean definitelyDoesNotContainName(@NotNull Name name) {
            return false;
        }

        @Override
        public String toString() {
            return "ErrorScope{" + debugMessage + '}';
        }

        @Override
        public void printScopeStructure(@NotNull Printer p) {
            p.println(getClass().getSimpleName(), ": ", debugMessage);
        }
    }

    private static class ThrowingScope implements MemberScope {
        private final String debugMessage;

        private ThrowingScope(@NotNull String message) {
            debugMessage = message;
        }

        @Nullable
        @Override
        public ClassifierDescriptor getContributedClassifier(@NotNull Name name, @NotNull LookupLocation location) {
            throw new IllegalStateException(debugMessage+", required name: " + name);
        }

        @Nullable
        @Override
        public DescriptorWithDeprecation getContributedClassifierIncludeDeprecated(
                @NotNull Name name, @NotNull LookupLocation location
        ) {
            throw new IllegalStateException(debugMessage + ", required name: " + name);
        }

        @NotNull
        @Override
        public Collection getContributedVariables(@NotNull Name name, @NotNull LookupLocation location) {
            throw new IllegalStateException(debugMessage+", required name: " + name);
        }

        @NotNull
        @Override
        public Collection getContributedFunctions(
                @NotNull Name name, @NotNull LookupLocation location
        ) {
            throw new IllegalStateException(debugMessage+", required name: " + name);
        }

        @NotNull
        @Override
        public Collection getContributedDescriptors(
                @NotNull DescriptorKindFilter kindFilter, @NotNull Function1 nameFilter
        ) {
            throw new IllegalStateException(debugMessage);
        }

        @NotNull
        @Override
        public Set getFunctionNames() {
            throw new IllegalStateException();
        }

        @NotNull
        @Override
        public Set getVariableNames() {
            throw new IllegalStateException();
        }

        @Override
        public Set getClassifierNames() {
            throw new IllegalStateException();
        }

        @Override
        public void recordLookup(@NotNull Name name, @NotNull LookupLocation location) {
            throw new IllegalStateException();
        }

        @Override
        public boolean definitelyDoesNotContainName(@NotNull Name name) {
            return false;
        }

        @Override
        public String toString() {
            return "ThrowingScope{" + debugMessage + '}';
        }

        @Override
        public void printScopeStructure(@NotNull Printer p) {
            p.println(getClass().getSimpleName(), ": ", debugMessage);
        }
    }

    private static final ErrorClassDescriptor ERROR_CLASS = new ErrorClassDescriptor(Name.special(""));

    private static class ErrorClassDescriptor extends ClassDescriptorImpl {
        public ErrorClassDescriptor(@NotNull Name name) {
            super(getErrorModule(), name,
                  Modality.OPEN, ClassKind.CLASS, Collections.emptyList(), SourceElement.NO_SOURCE,
                  /* isExternal = */ false, LockBasedStorageManager.NO_LOCKS
            );

            ClassConstructorDescriptorImpl
                    errorConstructor = ClassConstructorDescriptorImpl.create(this, Annotations.Companion.getEMPTY(), true, SourceElement.NO_SOURCE);
            errorConstructor.initialize(Collections.emptyList(),
                                        DescriptorVisibilities.INTERNAL);
            MemberScope memberScope = createErrorScope(getName().asString());
            errorConstructor.setReturnType(
                    new ErrorType(
                            createErrorTypeConstructorWithCustomDebugName("", this),
                            memberScope
                    )
            );

            initialize(memberScope, Collections.singleton(errorConstructor), errorConstructor);
        }

        @NotNull
        @Override
        public ClassDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
            return this;
        }

        @Override
        public String toString() {
            return getName().asString();
        }

        @NotNull
        @Override
        public MemberScope getMemberScope(@NotNull List typeArguments, @NotNull KotlinTypeRefiner kotlinTypeRefiner) {
            return createErrorScope("Error scope for class " + getName() + " with arguments: " + typeArguments);
        }

        @NotNull
        @Override
        public MemberScope getMemberScope(@NotNull TypeSubstitution typeSubstitution, @NotNull KotlinTypeRefiner kotlinTypeRefiner) {
            return createErrorScope("Error scope for class " + getName() + " with arguments: " + typeSubstitution);
        }
    }

    @NotNull
    public static ClassDescriptor createErrorClass(@NotNull String debugMessage) {
        return new ErrorClassDescriptor(Name.special(""));
    }

    @NotNull
    public static MemberScope createErrorScope(@NotNull String debugMessage) {
        return createErrorScope(debugMessage, false);
    }

    @NotNull
    public static MemberScope createErrorScope(@NotNull String debugMessage, boolean throwExceptions) {
        if (throwExceptions) {
            return new ThrowingScope(debugMessage);
        }
        return new ErrorScope(debugMessage);
    }

    // Do not move it into AbstractTypeConstructor.Companion because of cycle in initialization(see KT-13264)
    public static final SimpleType ERROR_TYPE_FOR_LOOP_IN_SUPERTYPES = createErrorType("");

    private static final KotlinType ERROR_PROPERTY_TYPE = createErrorType("");
    private static final PropertyDescriptor ERROR_PROPERTY = createErrorProperty();

    private static final Set ERROR_PROPERTY_GROUP = Collections.singleton(ERROR_PROPERTY);

    @NotNull
    private static PropertyDescriptorImpl createErrorProperty() {
        PropertyDescriptorImpl descriptor = PropertyDescriptorImpl.create(
                ERROR_CLASS,
                Annotations.Companion.getEMPTY(),
                Modality.OPEN,
                DescriptorVisibilities.PUBLIC,
                true,
                Name.special(""),
                CallableMemberDescriptor.Kind.DECLARATION,
                SourceElement.NO_SOURCE,
                false, false, false, false, false, false
        );
        descriptor.setType(ERROR_PROPERTY_TYPE, Collections.emptyList(), null, null);

        return descriptor;
    }

    @NotNull
    private static SimpleFunctionDescriptor createErrorFunction(@NotNull ErrorScope ownerScope) {
        ErrorSimpleFunctionDescriptorImpl function = new ErrorSimpleFunctionDescriptorImpl(ERROR_CLASS, ownerScope);
        function.initialize(
                null,
                null,
                Collections.emptyList(), // TODO
                Collections.emptyList(), // TODO
                createErrorType(""),
                Modality.OPEN,
                DescriptorVisibilities.PUBLIC
        );
        return function;
    }

    @NotNull
    public static SimpleType createErrorType(@NotNull String debugMessage) {
        return createErrorTypeWithArguments(debugMessage, Collections.emptyList());
    }

    @NotNull
    public static SimpleType createErrorTypeWithCustomDebugName(@NotNull String debugName) {
        return createErrorTypeWithCustomConstructor(debugName, createErrorTypeConstructorWithCustomDebugName(debugName));
    }

    @NotNull
    public static SimpleType createErrorTypeWithCustomConstructor(@NotNull String debugName, @NotNull TypeConstructor typeConstructor) {
        return new ErrorType(typeConstructor, createErrorScope(debugName));
    }

    @NotNull
    public static SimpleType createErrorTypeWithArguments(@NotNull String debugMessage, @NotNull List arguments) {
        return new ErrorType(createErrorTypeConstructor(debugMessage), createErrorScope(debugMessage), arguments, false);
    }

    @NotNull
    public static SimpleType createUnresolvedType(@NotNull String presentableName, @NotNull List arguments) {
        return new UnresolvedType(presentableName, createErrorTypeConstructor(presentableName), createErrorScope(presentableName),
                                  arguments, false);
    }

    @NotNull
    public static TypeConstructor createErrorTypeConstructor(@NotNull String debugMessage) {
        return createErrorTypeConstructorWithCustomDebugName("[ERROR : " + debugMessage + "]", ERROR_CLASS);
    }

    @NotNull
    public static TypeConstructor createErrorTypeConstructorWithCustomDebugName(@NotNull String debugName) {
        return createErrorTypeConstructorWithCustomDebugName(debugName, ERROR_CLASS);
    }

    @NotNull
    private static TypeConstructor createErrorTypeConstructorWithCustomDebugName(
            @NotNull final String debugName, @NotNull final ErrorClassDescriptor errorClass
    ) {
        return new TypeConstructor() {
            @NotNull
            @Override
            public List getParameters() {
                return emptyList();
            }

            @NotNull
            @Override
            public Collection getSupertypes() {
                return emptyList();
            }

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

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

            @Nullable
            @Override
            public ClassifierDescriptor getDeclarationDescriptor() {
                return errorClass;
            }

            @NotNull
            @Override
            public KotlinBuiltIns getBuiltIns() {
                return DefaultBuiltIns.getInstance();
            }

            @Override
            public String toString() {
                return debugName;
            }

            @TypeRefinement
            @Override
            @NotNull
            public TypeConstructor refine(@NotNull KotlinTypeRefiner kotlinTypeRefiner) {
                return this;
            }
        };
    }

    public static boolean containsErrorType(@Nullable KotlinType type) {
        if (type == null) return false;
        if (KotlinTypeKt.isError(type)) return true;
        for (TypeProjection projection : type.getArguments()) {
            if (!projection.isStarProjection() && containsErrorType(projection.getType())) return true;
        }
        return false;
    }

    public static boolean isError(@Nullable DeclarationDescriptor candidate) {
        if (candidate == null) return false;
        return isErrorClass(candidate) || isErrorClass(candidate.getContainingDeclaration()) || candidate == ERROR_MODULE;
    }

    private static boolean isErrorClass(@Nullable DeclarationDescriptor candidate) {
        return candidate instanceof ErrorClassDescriptor;
    }

    @NotNull
    public static ModuleDescriptor getErrorModule() {
        return ERROR_MODULE;
    }

    public static boolean isUninferredParameter(@Nullable KotlinType type) {
        return type != null && type.getConstructor() instanceof UninferredParameterTypeConstructor;
    }

    public static boolean containsUninferredParameter(@Nullable KotlinType type) {
        return TypeUtils.contains(type, new Function1() {
            @Override
            public Boolean invoke(UnwrappedType argumentType) {
                return isUninferredParameter(argumentType);
            }
        });
    }

    @NotNull
    public static KotlinType createUninferredParameterType(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
        return createErrorTypeWithCustomConstructor("Scope for error type for not inferred parameter: " + typeParameterDescriptor.getName(),
                                                    new UninferredParameterTypeConstructor(typeParameterDescriptor));
    }

    public static class UninferredParameterTypeConstructor implements TypeConstructor {
        private final TypeParameterDescriptor typeParameterDescriptor;
        private final TypeConstructor errorTypeConstructor;

        private UninferredParameterTypeConstructor(@NotNull TypeParameterDescriptor descriptor) {
            typeParameterDescriptor = descriptor;
            errorTypeConstructor = createErrorTypeConstructorWithCustomDebugName("CANT_INFER_TYPE_PARAMETER: " + descriptor.getName());
        }

        @NotNull
        public TypeParameterDescriptor getTypeParameterDescriptor() {
            return typeParameterDescriptor;
        }

        @NotNull
        @Override
        public List getParameters() {
            return errorTypeConstructor.getParameters();
        }

        @NotNull
        @Override
        public Collection getSupertypes() {
            return errorTypeConstructor.getSupertypes();
        }

        @Override
        public boolean isFinal() {
            return errorTypeConstructor.isFinal();
        }

        @Override
        public boolean isDenotable() {
            return errorTypeConstructor.isDenotable();
        }

        @Nullable
        @Override
        public ClassifierDescriptor getDeclarationDescriptor() {
            return errorTypeConstructor.getDeclarationDescriptor();
        }

        @NotNull
        @Override
        public KotlinBuiltIns getBuiltIns() {
            return DescriptorUtilsKt.getBuiltIns(typeParameterDescriptor);
        }

        @NotNull
        @Override
        public TypeConstructor refine(@NotNull KotlinTypeRefiner kotlinTypeRefiner) {
            return this;
        }
    }

    private ErrorUtils() {}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy