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    }