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.name.Name;
026 import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
027 import org.jetbrains.jet.lang.types.JetType;
028 import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
029 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
030 import org.jetbrains.k2js.translate.context.TranslationContext;
031
032 import java.util.List;
033 import java.util.Set;
034
035 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getSuperclassDescriptors;
036 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject;
037
038 public final class JsDescriptorUtils {
039
040 private JsDescriptorUtils() {
041 }
042
043 private static int valueParametersCount(@NotNull FunctionDescriptor functionDescriptor) {
044 return functionDescriptor.getValueParameters().size();
045 }
046
047 public static boolean hasParameters(@NotNull FunctionDescriptor functionDescriptor) {
048 return (valueParametersCount(functionDescriptor) > 0);
049 }
050
051 public static boolean isCompareTo(@NotNull FunctionDescriptor functionDescriptor) {
052 return (functionDescriptor.getName().equals(OperatorConventions.COMPARE_TO));
053 }
054
055 public static boolean isConstructorDescriptor(@NotNull CallableDescriptor descriptor) {
056 return (descriptor instanceof ConstructorDescriptor);
057 }
058
059 @Nullable
060 public static ClassDescriptor findAncestorClass(@NotNull List<ClassDescriptor> superclassDescriptors) {
061 for (ClassDescriptor descriptor : superclassDescriptors) {
062 if (descriptor.getKind() == ClassKind.CLASS || descriptor.getKind() == ClassKind.ENUM_CLASS) {
063 return descriptor;
064 }
065 }
066 return null;
067 }
068
069 @Nullable
070 public static ClassDescriptor getSuperclass(@NotNull ClassDescriptor classDescriptor) {
071 return findAncestorClass(getSuperclassDescriptors(classDescriptor));
072 }
073
074 @NotNull
075 public static DeclarationDescriptor getContainingDeclaration(@NotNull DeclarationDescriptor descriptor) {
076 DeclarationDescriptor containing = descriptor.getContainingDeclaration();
077 assert containing != null : "Should be called on objects that have containing declaration.";
078 return containing;
079 }
080
081 public static boolean isExtension(@NotNull CallableDescriptor functionDescriptor) {
082 return (functionDescriptor.getReceiverParameter() != null);
083 }
084
085 //TODO: why callable descriptor
086 @Nullable
087 public static DeclarationDescriptor getExpectedThisDescriptor(@NotNull CallableDescriptor callableDescriptor) {
088 ReceiverParameterDescriptor expectedThisObject = callableDescriptor.getExpectedThisObject();
089 if (expectedThisObject == null) {
090 return null;
091 }
092 return getDeclarationDescriptorForReceiver(expectedThisObject.getValue());
093 }
094
095 @NotNull
096 public static DeclarationDescriptor getDeclarationDescriptorForReceiver
097 (@NotNull ReceiverValue receiverParameter) {
098 DeclarationDescriptor declarationDescriptor =
099 receiverParameter.getType().getConstructor().getDeclarationDescriptor();
100 //TODO: WHY assert?
101 assert declarationDescriptor != null;
102 return declarationDescriptor.getOriginal();
103 }
104
105 @Nullable
106 public static DeclarationDescriptor getExpectedReceiverDescriptor(@NotNull CallableDescriptor callableDescriptor) {
107 ReceiverParameterDescriptor receiverParameter = callableDescriptor.getReceiverParameter();
108 if (receiverParameter == null) {
109 return null;
110 }
111 return getDeclarationDescriptorForReceiver(receiverParameter.getValue());
112 }
113
114 //TODO: maybe we have similar routine
115 @Nullable
116 public static ClassDescriptor getContainingClass(@NotNull DeclarationDescriptor descriptor) {
117 DeclarationDescriptor containing = descriptor.getContainingDeclaration();
118 while (containing != null) {
119 if (containing instanceof ClassDescriptor && !isClassObject(containing)) {
120 return (ClassDescriptor) containing;
121 }
122 containing = containing.getContainingDeclaration();
123 }
124 return null;
125 }
126
127 @Nullable
128 public static FunctionDescriptor getOverriddenDescriptor(@NotNull FunctionDescriptor functionDescriptor) {
129 Set<? extends FunctionDescriptor> overriddenDescriptors = functionDescriptor.getOverriddenDescriptors();
130 if (overriddenDescriptors.isEmpty()) {
131 return null;
132 }
133 else {
134 //TODO: for now translator can't deal with multiple inheritance good enough
135 return overriddenDescriptors.iterator().next();
136 }
137 }
138
139 private static boolean isDefaultAccessor(@Nullable PropertyAccessorDescriptor accessorDescriptor) {
140 return accessorDescriptor == null || accessorDescriptor.isDefault();
141 }
142
143 public static boolean isAsPrivate(@NotNull PropertyDescriptor propertyDescriptor) {
144 return isExtension(propertyDescriptor) ||
145 !isDefaultAccessor(propertyDescriptor.getGetter()) ||
146 !isDefaultAccessor(propertyDescriptor.getSetter());
147 }
148
149 public static boolean isStandardDeclaration(@NotNull DeclarationDescriptor descriptor) {
150 NamespaceDescriptor namespace = getContainingNamespace(descriptor);
151 if (namespace == null) {
152 return false;
153 }
154 return namespace.equals(KotlinBuiltIns.getInstance().getBuiltInsScope().getContainingDeclaration());
155 }
156
157 @Nullable
158 public static NamespaceDescriptor getContainingNamespace(@NotNull DeclarationDescriptor descriptor) {
159 return DescriptorUtils.getParentOfType(descriptor, NamespaceDescriptor.class);
160 }
161
162 @Nullable
163 public static Name getNameIfStandardType(@NotNull JetExpression expression, @NotNull TranslationContext context) {
164 JetType type = context.bindingContext().get(BindingContext.EXPRESSION_TYPE, expression);
165 return type != null ? getNameIfStandardType(type) : null;
166 }
167
168 @Nullable
169 public static Name getNameIfStandardType(@NotNull JetType type) {
170 ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
171 if (descriptor != null && descriptor.getContainingDeclaration() == KotlinBuiltIns.getInstance().getBuiltInsPackage()) {
172 return descriptor.getName();
173 }
174
175 return null;
176 }
177 }