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 041 public final class JsDescriptorUtils { 042 // TODO: maybe we should use external annotations or something else. 043 private static final Set<String> FAKE_CLASSES = ContainerUtil.immutableSet( 044 getFqNameSafe(KotlinBuiltIns.getInstance().getAny()).asString(), 045 getFqNameSafe(KotlinBuiltIns.getInstance().getIterable()).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 FunctionDescriptor functionDescriptor) { 060 return (functionDescriptor.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 return !FAKE_CLASSES.contains(getFqNameSafe(classDescriptor).asString()); 086 } 087 }); 088 } 089 090 @NotNull 091 public static DeclarationDescriptor getContainingDeclaration(@NotNull DeclarationDescriptor descriptor) { 092 DeclarationDescriptor containing = descriptor.getContainingDeclaration(); 093 assert containing != null : "Should be called on objects that have containing declaration."; 094 return containing; 095 } 096 097 public static boolean isExtension(@NotNull CallableDescriptor functionDescriptor) { 098 return (functionDescriptor.getReceiverParameter() != null); 099 } 100 101 public static boolean isOverride(@NotNull CallableMemberDescriptor descriptor) { 102 return !descriptor.getOverriddenDescriptors().isEmpty(); 103 } 104 105 //TODO: why callable descriptor 106 @Nullable 107 public static DeclarationDescriptor getExpectedThisDescriptor(@NotNull CallableDescriptor callableDescriptor) { 108 ReceiverParameterDescriptor expectedThisObject = callableDescriptor.getExpectedThisObject(); 109 if (expectedThisObject == null) { 110 return null; 111 } 112 return getDeclarationDescriptorForReceiver(expectedThisObject.getValue()); 113 } 114 115 @NotNull 116 public static DeclarationDescriptor getDeclarationDescriptorForReceiver(@NotNull ReceiverValue receiverParameter) { 117 DeclarationDescriptor declarationDescriptor; 118 119 if (receiverParameter instanceof ThisReceiver) { 120 declarationDescriptor = ((ThisReceiver) receiverParameter).getDeclarationDescriptor(); 121 } 122 else { 123 throw new UnsupportedOperationException("Unsupported receiver type: " + receiverParameter); 124 } 125 126 return declarationDescriptor.getOriginal(); 127 } 128 129 @Nullable 130 public static DeclarationDescriptor getExpectedReceiverDescriptor(@NotNull CallableDescriptor callableDescriptor) { 131 ReceiverParameterDescriptor receiverParameter = callableDescriptor.getReceiverParameter(); 132 if (receiverParameter == null) { 133 return null; 134 } 135 return getDeclarationDescriptorForReceiver(receiverParameter.getValue()); 136 } 137 138 //TODO: maybe we have similar routine 139 @Nullable 140 public static ClassDescriptor getContainingClass(@NotNull DeclarationDescriptor descriptor) { 141 DeclarationDescriptor containing = descriptor.getContainingDeclaration(); 142 while (containing != null) { 143 if (containing instanceof ClassDescriptor && !isClassObject(containing)) { 144 return (ClassDescriptor) containing; 145 } 146 containing = containing.getContainingDeclaration(); 147 } 148 return null; 149 } 150 151 @Nullable 152 public static FunctionDescriptor getOverriddenDescriptor(@NotNull FunctionDescriptor functionDescriptor) { 153 Set<? extends FunctionDescriptor> overriddenDescriptors = functionDescriptor.getOverriddenDescriptors(); 154 if (overriddenDescriptors.isEmpty()) { 155 return null; 156 } 157 else { 158 //TODO: for now translator can't deal with multiple inheritance good enough 159 return overriddenDescriptors.iterator().next(); 160 } 161 } 162 163 private static boolean isDefaultAccessor(@Nullable PropertyAccessorDescriptor accessorDescriptor) { 164 return accessorDescriptor == null || accessorDescriptor.isDefault(); 165 } 166 167 public static boolean isSimpleFinalProperty(@NotNull PropertyDescriptor propertyDescriptor) { 168 return !isExtension(propertyDescriptor) && 169 isDefaultAccessor(propertyDescriptor.getGetter()) && 170 isDefaultAccessor(propertyDescriptor.getSetter()) && 171 !propertyDescriptor.getModality().isOverridable(); 172 } 173 174 public static boolean isBuiltin(@NotNull DeclarationDescriptor descriptor) { 175 PackageFragmentDescriptor containingPackageFragment = DescriptorUtils.getParentOfType(descriptor, PackageFragmentDescriptor.class); 176 return containingPackageFragment == KotlinBuiltIns.getInstance().getBuiltInsPackageFragment(); 177 } 178 179 @Nullable 180 public static Name getNameIfStandardType(@NotNull JetExpression expression, @NotNull TranslationContext context) { 181 JetType type = context.bindingContext().get(BindingContext.EXPRESSION_TYPE, expression); 182 return type != null ? getNameIfStandardType(type) : null; 183 } 184 185 @Nullable 186 public static Name getNameIfStandardType(@NotNull JetType type) { 187 ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); 188 if (descriptor != null && descriptor.getContainingDeclaration() == KotlinBuiltIns.getInstance().getBuiltInsPackageFragment()) { 189 return descriptor.getName(); 190 } 191 192 return null; 193 } 194 }