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 org.jetbrains.annotations.NotNull;
020 import org.jetbrains.annotations.Nullable;
021 import org.jetbrains.jet.lang.descriptors.*;
022 import org.jetbrains.jet.lang.psi.JetExpression;
023 import org.jetbrains.jet.lang.resolve.BindingContext;
024 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
025 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
026 import org.jetbrains.jet.lang.resolve.name.Name;
027 import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
028 import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
029 import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
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.List;
036 import java.util.Set;
037
038 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getSuperclassDescriptors;
039 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject;
040
041 public 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 }