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 017package org.jetbrains.k2js.translate.utils; 018 019import org.jetbrains.annotations.NotNull; 020import org.jetbrains.annotations.Nullable; 021import org.jetbrains.jet.lang.descriptors.*; 022import org.jetbrains.jet.lang.psi.JetExpression; 023import org.jetbrains.jet.lang.resolve.BindingContext; 024import org.jetbrains.jet.lang.resolve.DescriptorUtils; 025import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; 026import org.jetbrains.jet.lang.resolve.name.Name; 027import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver; 028import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver; 029import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; 030import org.jetbrains.jet.lang.types.JetType; 031import org.jetbrains.jet.lang.types.expressions.OperatorConventions; 032import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 033import org.jetbrains.k2js.translate.context.TranslationContext; 034 035import java.util.List; 036import java.util.Set; 037 038import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getSuperclassDescriptors; 039import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject; 040 041public final class JsDescriptorUtils { 042 043 private JsDescriptorUtils() { 044 } 045 046 private static int valueParametersCount(@NotNull FunctionDescriptor functionDescriptor) { 047 return functionDescriptor.getValueParameters().size(); 048 } 049 050 public static boolean hasParameters(@NotNull FunctionDescriptor functionDescriptor) { 051 return (valueParametersCount(functionDescriptor) > 0); 052 } 053 054 public static boolean isCompareTo(@NotNull FunctionDescriptor functionDescriptor) { 055 return (functionDescriptor.getName().equals(OperatorConventions.COMPARE_TO)); 056 } 057 058 public static boolean isConstructorDescriptor(@NotNull CallableDescriptor descriptor) { 059 return (descriptor instanceof ConstructorDescriptor); 060 } 061 062 @Nullable 063 public static ClassDescriptor findAncestorClass(@NotNull List<ClassDescriptor> superclassDescriptors) { 064 for (ClassDescriptor descriptor : superclassDescriptors) { 065 if (descriptor.getKind() == ClassKind.CLASS) { 066 return descriptor; 067 } 068 } 069 return null; 070 } 071 072 @Nullable 073 public static ClassDescriptor getSuperclass(@NotNull ClassDescriptor classDescriptor) { 074 return findAncestorClass(getSuperclassDescriptors(classDescriptor)); 075 } 076 077 @NotNull 078 public static DeclarationDescriptor getContainingDeclaration(@NotNull DeclarationDescriptor descriptor) { 079 DeclarationDescriptor containing = descriptor.getContainingDeclaration(); 080 assert containing != null : "Should be called on objects that have containing declaration."; 081 return containing; 082 } 083 084 public static boolean isExtension(@NotNull CallableDescriptor functionDescriptor) { 085 return (functionDescriptor.getReceiverParameter() != null); 086 } 087 088 //TODO: why callable descriptor 089 @Nullable 090 public static DeclarationDescriptor getExpectedThisDescriptor(@NotNull CallableDescriptor callableDescriptor) { 091 ReceiverParameterDescriptor expectedThisObject = callableDescriptor.getExpectedThisObject(); 092 if (expectedThisObject == null) { 093 return null; 094 } 095 return getDeclarationDescriptorForReceiver(expectedThisObject.getValue()); 096 } 097 098 @NotNull 099 public static DeclarationDescriptor getDeclarationDescriptorForReceiver 100 (@NotNull ReceiverValue receiverParameter) { 101 DeclarationDescriptor declarationDescriptor = 102 receiverParameter.getType().getConstructor().getDeclarationDescriptor(); 103 //TODO: WHY assert? 104 assert declarationDescriptor != null; 105 return declarationDescriptor.getOriginal(); 106 } 107 108 @Nullable 109 public static DeclarationDescriptor getExpectedReceiverDescriptor(@NotNull CallableDescriptor callableDescriptor) { 110 ReceiverParameterDescriptor receiverParameter = callableDescriptor.getReceiverParameter(); 111 if (receiverParameter == null) { 112 return null; 113 } 114 return getDeclarationDescriptorForReceiver(receiverParameter.getValue()); 115 } 116 117 //TODO: maybe we have similar routine 118 @Nullable 119 public static ClassDescriptor getContainingClass(@NotNull DeclarationDescriptor descriptor) { 120 DeclarationDescriptor containing = descriptor.getContainingDeclaration(); 121 while (containing != null) { 122 if (containing instanceof ClassDescriptor && !isClassObject(containing)) { 123 return (ClassDescriptor) containing; 124 } 125 containing = containing.getContainingDeclaration(); 126 } 127 return null; 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 isAsPrivate(@NotNull PropertyDescriptor propertyDescriptor) { 147 return isExtension(propertyDescriptor) || 148 !isDefaultAccessor(propertyDescriptor.getGetter()) || 149 !isDefaultAccessor(propertyDescriptor.getSetter()); 150 } 151 152 public static boolean isStandardDeclaration(@NotNull DeclarationDescriptor descriptor) { 153 NamespaceDescriptor namespace = getContainingNamespace(descriptor); 154 if (namespace == null) { 155 return false; 156 } 157 return namespace.equals(KotlinBuiltIns.getInstance().getBuiltInsScope().getContainingDeclaration()); 158 } 159 160 @Nullable 161 public static NamespaceDescriptor getContainingNamespace(@NotNull DeclarationDescriptor descriptor) { 162 return DescriptorUtils.getParentOfType(descriptor, NamespaceDescriptor.class); 163 } 164 165 @Nullable 166 public static Name getNameIfStandardType(@NotNull JetExpression expression, @NotNull TranslationContext context) { 167 JetType type = context.bindingContext().get(BindingContext.EXPRESSION_TYPE, expression); 168 return type != null ? getNameIfStandardType(type) : null; 169 } 170 171 @Nullable 172 public static Name getNameIfStandardType(@NotNull JetType type) { 173 ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); 174 if (descriptor != null && descriptor.getContainingDeclaration() == KotlinBuiltIns.getInstance().getBuiltInsPackage()) { 175 return descriptor.getName(); 176 } 177 178 return null; 179 } 180 181 @NotNull 182 public static DeclarationDescriptor getDeclarationDescriptorForExtensionCallReceiver( 183 @NotNull ResolvedCall<? extends CallableDescriptor> resolvedCall 184 ) { 185 ReceiverValue receiverArgument = resolvedCall.getReceiverArgument(); 186 if (receiverArgument instanceof ExtensionReceiver) { 187 return ((ExtensionReceiver) receiverArgument).getDeclarationDescriptor(); 188 } 189 if (receiverArgument instanceof ClassReceiver) { 190 return ((ClassReceiver) receiverArgument).getDeclarationDescriptor(); 191 } 192 throw new IllegalStateException("Unexpected receiver of type " + receiverArgument.getClass()); 193 } 194}