001 /* 002 * Copyright 2010-2013 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.jetbrains.k2js.translate.utils; 018 019 import com.intellij.openapi.util.Condition; 020 import com.intellij.util.containers.ContainerUtil; 021 import org.jetbrains.annotations.NotNull; 022 import org.jetbrains.annotations.Nullable; 023 import org.jetbrains.jet.lang.descriptors.*; 024 import org.jetbrains.jet.lang.psi.JetExpression; 025 import org.jetbrains.jet.lang.resolve.BindingContext; 026 import org.jetbrains.jet.lang.resolve.DescriptorUtils; 027 import org.jetbrains.jet.lang.resolve.name.Name; 028 import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; 029 import org.jetbrains.jet.lang.resolve.scopes.receivers.ThisReceiver; 030 import org.jetbrains.jet.lang.types.JetType; 031 import org.jetbrains.jet.lang.types.expressions.OperatorConventions; 032 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 033 import org.jetbrains.k2js.translate.context.TranslationContext; 034 035 import java.util.Collection; 036 import java.util.List; 037 import java.util.Set; 038 039 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*; 040 import static org.jetbrains.k2js.translate.utils.AnnotationsUtils.isNativeObject; 041 042 public final class JsDescriptorUtils { 043 // TODO: maybe we should use external annotations or something else. 044 private static final Set<String> FAKE_CLASSES = ContainerUtil.immutableSet( 045 getFqNameSafe(KotlinBuiltIns.getInstance().getAny()).asString() 046 ); 047 048 private JsDescriptorUtils() { 049 } 050 051 private static int valueParametersCount(@NotNull FunctionDescriptor functionDescriptor) { 052 return functionDescriptor.getValueParameters().size(); 053 } 054 055 public static boolean hasParameters(@NotNull FunctionDescriptor functionDescriptor) { 056 return (valueParametersCount(functionDescriptor) > 0); 057 } 058 059 public static boolean isCompareTo(@NotNull CallableDescriptor descriptor) { 060 return descriptor.getName().equals(OperatorConventions.COMPARE_TO); 061 } 062 063 @Nullable 064 public static ClassDescriptor findAncestorClass(@NotNull List<ClassDescriptor> superclassDescriptors) { 065 for (ClassDescriptor descriptor : superclassDescriptors) { 066 if (descriptor.getKind() == ClassKind.CLASS || descriptor.getKind() == ClassKind.ENUM_CLASS) { 067 return descriptor; 068 } 069 } 070 return null; 071 } 072 073 @Nullable 074 public static ClassDescriptor getSuperclass(@NotNull ClassDescriptor classDescriptor) { 075 return findAncestorClass(getSuperclassDescriptors(classDescriptor)); 076 } 077 078 @NotNull 079 public static List<JetType> getSupertypesWithoutFakes(ClassDescriptor descriptor) { 080 Collection<JetType> supertypes = descriptor.getTypeConstructor().getSupertypes(); 081 return ContainerUtil.filter(supertypes, new Condition<JetType>() { 082 @Override 083 public boolean value(JetType type) { 084 ClassDescriptor classDescriptor = getClassDescriptorForType(type); 085 086 return !FAKE_CLASSES.contains(getFqNameSafe(classDescriptor).asString()) && 087 !(classDescriptor.getKind() == ClassKind.TRAIT && isNativeObject(classDescriptor)); 088 } 089 }); 090 } 091 092 @NotNull 093 public static DeclarationDescriptor getContainingDeclaration(@NotNull DeclarationDescriptor descriptor) { 094 DeclarationDescriptor containing = descriptor.getContainingDeclaration(); 095 assert containing != null : "Should be called on objects that have containing declaration."; 096 return containing; 097 } 098 099 @NotNull 100 public static ReceiverParameterDescriptor getReceiverParameterForReceiver(@NotNull ReceiverValue receiverParameter) { 101 DeclarationDescriptor declarationDescriptor = getDeclarationDescriptorForReceiver(receiverParameter); 102 return getReceiverParameterForDeclaration(declarationDescriptor); 103 } 104 105 @NotNull 106 private static DeclarationDescriptor getDeclarationDescriptorForReceiver(@NotNull ReceiverValue receiverParameter) { 107 if (receiverParameter instanceof ThisReceiver) { 108 DeclarationDescriptor declarationDescriptor = ((ThisReceiver) receiverParameter).getDeclarationDescriptor(); 109 return declarationDescriptor.getOriginal(); 110 } 111 112 throw new UnsupportedOperationException("Unsupported receiver type: " + receiverParameter.getClass() + 113 ", receiverParameter = " + receiverParameter); 114 } 115 116 public static ReceiverParameterDescriptor getReceiverParameterForDeclaration(DeclarationDescriptor declarationDescriptor) { 117 if (declarationDescriptor instanceof ClassDescriptor) { 118 return ((ClassDescriptor) declarationDescriptor).getThisAsReceiverParameter(); 119 } 120 else if (declarationDescriptor instanceof CallableMemberDescriptor) { 121 ReceiverParameterDescriptor receiverDescriptor = ((CallableMemberDescriptor) declarationDescriptor).getExtensionReceiverParameter(); 122 assert receiverDescriptor != null; 123 return receiverDescriptor; 124 } 125 126 throw new UnsupportedOperationException("Unsupported declaration type: " + declarationDescriptor.getClass() + 127 ", declarationDescriptor = " + declarationDescriptor); 128 } 129 130 @Nullable 131 public static FunctionDescriptor getOverriddenDescriptor(@NotNull FunctionDescriptor functionDescriptor) { 132 Set<? extends FunctionDescriptor> overriddenDescriptors = functionDescriptor.getOverriddenDescriptors(); 133 if (overriddenDescriptors.isEmpty()) { 134 return null; 135 } 136 else { 137 //TODO: for now translator can't deal with multiple inheritance good enough 138 return overriddenDescriptors.iterator().next(); 139 } 140 } 141 142 private static boolean isDefaultAccessor(@Nullable PropertyAccessorDescriptor accessorDescriptor) { 143 return accessorDescriptor == null || accessorDescriptor.isDefault(); 144 } 145 146 public static boolean isSimpleFinalProperty(@NotNull PropertyDescriptor propertyDescriptor) { 147 return !isExtension(propertyDescriptor) && 148 isDefaultAccessor(propertyDescriptor.getGetter()) && 149 isDefaultAccessor(propertyDescriptor.getSetter()) && 150 !propertyDescriptor.getModality().isOverridable(); 151 } 152 153 public static boolean isBuiltin(@NotNull DeclarationDescriptor descriptor) { 154 PackageFragmentDescriptor containingPackageFragment = DescriptorUtils.getParentOfType(descriptor, PackageFragmentDescriptor.class); 155 return containingPackageFragment == KotlinBuiltIns.getInstance().getBuiltInsPackageFragment(); 156 } 157 158 @Nullable 159 public static Name getNameIfStandardType(@NotNull JetExpression expression, @NotNull TranslationContext context) { 160 JetType type = context.bindingContext().get(BindingContext.EXPRESSION_TYPE, expression); 161 return type != null ? getNameIfStandardType(type) : null; 162 } 163 164 @Nullable 165 public static Name getNameIfStandardType(@NotNull JetType type) { 166 ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); 167 if (descriptor != null && descriptor.getContainingDeclaration() == KotlinBuiltIns.getInstance().getBuiltInsPackageFragment()) { 168 return descriptor.getName(); 169 } 170 171 return null; 172 } 173 }