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.types.JetType; 030 import org.jetbrains.jet.lang.types.expressions.OperatorConventions; 031 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 032 import org.jetbrains.k2js.translate.context.TranslationContext; 033 034 import java.util.Collection; 035 import java.util.List; 036 import java.util.Set; 037 038 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*; 039 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getFQName; 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 getFQName(KotlinBuiltIns.getInstance().getAny()).toSafe().asString(), 045 "jet.Iterable" 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(getFQName(classDescriptor).toSafe().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 //TODO: why callable descriptor 102 @Nullable 103 public static DeclarationDescriptor getExpectedThisDescriptor(@NotNull CallableDescriptor callableDescriptor) { 104 ReceiverParameterDescriptor expectedThisObject = callableDescriptor.getExpectedThisObject(); 105 if (expectedThisObject == null) { 106 return null; 107 } 108 return getDeclarationDescriptorForReceiver(expectedThisObject.getValue()); 109 } 110 111 @NotNull 112 public static DeclarationDescriptor getDeclarationDescriptorForReceiver 113 (@NotNull ReceiverValue receiverParameter) { 114 DeclarationDescriptor declarationDescriptor = 115 receiverParameter.getType().getConstructor().getDeclarationDescriptor(); 116 //TODO: WHY assert? 117 assert declarationDescriptor != null; 118 return declarationDescriptor.getOriginal(); 119 } 120 121 @Nullable 122 public static DeclarationDescriptor getExpectedReceiverDescriptor(@NotNull CallableDescriptor callableDescriptor) { 123 ReceiverParameterDescriptor receiverParameter = callableDescriptor.getReceiverParameter(); 124 if (receiverParameter == null) { 125 return null; 126 } 127 return getDeclarationDescriptorForReceiver(receiverParameter.getValue()); 128 } 129 130 //TODO: maybe we have similar routine 131 @Nullable 132 public static ClassDescriptor getContainingClass(@NotNull DeclarationDescriptor descriptor) { 133 DeclarationDescriptor containing = descriptor.getContainingDeclaration(); 134 while (containing != null) { 135 if (containing instanceof ClassDescriptor && !isClassObject(containing)) { 136 return (ClassDescriptor) containing; 137 } 138 containing = containing.getContainingDeclaration(); 139 } 140 return null; 141 } 142 143 @Nullable 144 public static FunctionDescriptor getOverriddenDescriptor(@NotNull FunctionDescriptor functionDescriptor) { 145 Set<? extends FunctionDescriptor> overriddenDescriptors = functionDescriptor.getOverriddenDescriptors(); 146 if (overriddenDescriptors.isEmpty()) { 147 return null; 148 } 149 else { 150 //TODO: for now translator can't deal with multiple inheritance good enough 151 return overriddenDescriptors.iterator().next(); 152 } 153 } 154 155 private static boolean isDefaultAccessor(@Nullable PropertyAccessorDescriptor accessorDescriptor) { 156 return accessorDescriptor == null || accessorDescriptor.isDefault(); 157 } 158 159 public static boolean isSimpleFinalProperty(@NotNull PropertyDescriptor propertyDescriptor) { 160 return !isExtension(propertyDescriptor) && 161 isDefaultAccessor(propertyDescriptor.getGetter()) && 162 isDefaultAccessor(propertyDescriptor.getSetter()) && 163 !propertyDescriptor.getModality().isOverridable(); 164 } 165 166 public static boolean isStandardDeclaration(@NotNull DeclarationDescriptor descriptor) { 167 NamespaceDescriptor namespace = getContainingNamespace(descriptor); 168 if (namespace == null) { 169 return false; 170 } 171 return namespace.equals(KotlinBuiltIns.getInstance().getBuiltInsScope().getContainingDeclaration()); 172 } 173 174 @Nullable 175 public static NamespaceDescriptor getContainingNamespace(@NotNull DeclarationDescriptor descriptor) { 176 return DescriptorUtils.getParentOfType(descriptor, NamespaceDescriptor.class); 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().getBuiltInsPackage()) { 189 return descriptor.getName(); 190 } 191 192 return null; 193 } 194 }