org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils Maven / Gradle / Ivy
/*
* 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.js.translate.utils;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.js.translate.context.Namer;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallsKt;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver;
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
import org.jetbrains.kotlin.util.OperatorNameConventions;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import static org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.isNativeObject;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
public final class JsDescriptorUtils {
// TODO: maybe we should use external annotations or something else.
private static final Set FAKE_CLASSES = ContainerUtil.immutableSet(
KotlinBuiltIns.FQ_NAMES.any.asString()
);
private JsDescriptorUtils() {
}
private static int valueParametersCount(@NotNull FunctionDescriptor functionDescriptor) {
return functionDescriptor.getValueParameters().size();
}
public static boolean hasParameters(@NotNull FunctionDescriptor functionDescriptor) {
return (valueParametersCount(functionDescriptor) > 0);
}
public static boolean isCompareTo(@NotNull CallableDescriptor descriptor) {
return descriptor.getName().equals(OperatorNameConventions.COMPARE_TO);
}
@Nullable
public static ClassDescriptor findAncestorClass(@NotNull List superclassDescriptors) {
for (ClassDescriptor descriptor : superclassDescriptors) {
if (descriptor.getKind() == ClassKind.CLASS || descriptor.getKind() == ClassKind.ENUM_CLASS) {
return descriptor;
}
}
return null;
}
@Nullable
public static ClassDescriptor getSuperclass(@NotNull ClassDescriptor classDescriptor) {
return findAncestorClass(getSuperclassDescriptors(classDescriptor));
}
@NotNull
public static List getSupertypesWithoutFakes(ClassDescriptor descriptor) {
Collection supertypes = descriptor.getTypeConstructor().getSupertypes();
return ContainerUtil.filter(supertypes, type -> {
ClassDescriptor classDescriptor = getClassDescriptorForType(type);
return !FAKE_CLASSES.contains(getFqNameSafe(classDescriptor).asString()) &&
!(classDescriptor.getKind() == ClassKind.INTERFACE && isNativeObject(classDescriptor));
});
}
@NotNull
public static DeclarationDescriptor getContainingDeclaration(@NotNull DeclarationDescriptor descriptor) {
DeclarationDescriptor containing = descriptor.getContainingDeclaration();
assert containing != null : "Should be called on objects that have containing declaration.";
return containing;
}
@NotNull
public static ReceiverParameterDescriptor getReceiverParameterForReceiver(@NotNull ReceiverValue receiverParameter) {
DeclarationDescriptor declarationDescriptor = getDeclarationDescriptorForReceiver(receiverParameter);
return getReceiverParameterForDeclaration(declarationDescriptor);
}
@NotNull
private static DeclarationDescriptor getDeclarationDescriptorForReceiver(@NotNull ReceiverValue receiverParameter) {
if (receiverParameter instanceof ImplicitReceiver) {
DeclarationDescriptor declarationDescriptor = ((ImplicitReceiver) receiverParameter).getDeclarationDescriptor();
return declarationDescriptor.getOriginal();
}
throw new UnsupportedOperationException("Unsupported receiver type: " + receiverParameter.getClass() +
", receiverParameter = " + receiverParameter);
}
@NotNull
public static ReceiverParameterDescriptor getReceiverParameterForDeclaration(DeclarationDescriptor declarationDescriptor) {
if (declarationDescriptor instanceof ClassDescriptor) {
return ((ClassDescriptor) declarationDescriptor).getThisAsReceiverParameter();
}
else if (declarationDescriptor instanceof CallableMemberDescriptor) {
ReceiverParameterDescriptor receiverDescriptor = ((CallableMemberDescriptor) declarationDescriptor).getExtensionReceiverParameter();
assert receiverDescriptor != null;
return receiverDescriptor;
}
throw new UnsupportedOperationException("Unsupported declaration type: " + declarationDescriptor.getClass() +
", declarationDescriptor = " + declarationDescriptor);
}
private static boolean isDefaultAccessor(@Nullable PropertyAccessorDescriptor accessorDescriptor) {
return accessorDescriptor == null || accessorDescriptor.isDefault();
}
public static boolean sideEffectsPossibleOnRead(@NotNull PropertyDescriptor property) {
return DynamicCallsKt.isDynamic(property) || !isDefaultAccessor(property.getGetter()) ||
ModalityKt.isOverridableOrOverrides(property) || isStaticInitializationPossible(property);
}
private static boolean isStaticInitializationPossible(PropertyDescriptor property) {
DeclarationDescriptor container = property.getContainingDeclaration();
return container instanceof PackageFragmentDescriptor || DescriptorUtils.isObject(container);
}
public static boolean isSimpleFinalProperty(@NotNull PropertyDescriptor propertyDescriptor) {
return !isExtension(propertyDescriptor) &&
isDefaultAccessor(propertyDescriptor.getGetter()) &&
isDefaultAccessor(propertyDescriptor.getSetter()) &&
!TranslationUtils.shouldAccessViaFunctions(propertyDescriptor) &&
!ModalityKt.isOverridableOrOverrides(propertyDescriptor);
}
@NotNull
public static String getModuleName(@NotNull DeclarationDescriptor descriptor) {
ModuleDescriptor moduleDescriptor = DescriptorUtils.getContainingModule(findRealInlineDeclaration(descriptor));
if (DescriptorUtils.getContainingModule(descriptor) == moduleDescriptor.getBuiltIns().getBuiltInsModule()) {
return Namer.KOTLIN_LOWER_NAME;
}
String moduleName = moduleDescriptor.getName().asString();
return moduleName.substring(1, moduleName.length() - 1);
}
@NotNull
public static DeclarationDescriptor findRealInlineDeclaration(@NotNull DeclarationDescriptor descriptor) {
if (descriptor instanceof FunctionDescriptor) {
FunctionDescriptor d = (FunctionDescriptor) descriptor;
if (d.getKind().isReal() || !d.isInline()) return descriptor;
CallableMemberDescriptor real = findRealDeclaration(d);
assert real != null : "Couldn't find definition of a fake inline descriptor " + descriptor;
return real;
}
return descriptor;
}
@Nullable
private static FunctionDescriptor findRealDeclaration(FunctionDescriptor descriptor) {
if (descriptor.getModality() == Modality.ABSTRACT) return null;
if (descriptor.getKind().isReal()) return descriptor;
for (FunctionDescriptor o : descriptor.getOverriddenDescriptors()) {
FunctionDescriptor child = findRealDeclaration(o);
if (child != null) {
return child;
}
}
return null;
}
public static boolean isImmediateSubtypeOfError(@NotNull ClassDescriptor descriptor) {
if (!isExceptionClass(descriptor)) return false;
ClassDescriptor superClass = DescriptorUtilsKt.getSuperClassOrAny(descriptor);
return TypeUtilsKt.isNotNullThrowable(superClass.getDefaultType()) || AnnotationsUtils.isNativeObject(superClass);
}
public static boolean isExceptionClass(@NotNull ClassDescriptor descriptor) {
ModuleDescriptor module = DescriptorUtils.getContainingModule(descriptor);
return TypeUtilsKt.isSubtypeOf(descriptor.getDefaultType(), module.getBuiltIns().getThrowable().getDefaultType());
}
}