001    /*
002     * Copyright 2010-2015 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.kotlin.resolve;
018    
019    import kotlin.jvm.functions.Function1;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.Nullable;
022    import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
023    import org.jetbrains.kotlin.descriptors.*;
024    import org.jetbrains.kotlin.descriptors.annotations.Annotated;
025    import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
026    import org.jetbrains.kotlin.descriptors.annotations.Annotations;
027    import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
028    import org.jetbrains.kotlin.descriptors.impl.FunctionExpressionDescriptor;
029    import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
030    import org.jetbrains.kotlin.incremental.components.LookupLocation;
031    import org.jetbrains.kotlin.name.FqName;
032    import org.jetbrains.kotlin.name.FqNameUnsafe;
033    import org.jetbrains.kotlin.name.Name;
034    import org.jetbrains.kotlin.name.SpecialNames;
035    import org.jetbrains.kotlin.resolve.constants.ConstantValue;
036    import org.jetbrains.kotlin.resolve.constants.StringValue;
037    import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter;
038    import org.jetbrains.kotlin.resolve.scopes.FilteringScope;
039    import org.jetbrains.kotlin.resolve.scopes.JetScope;
040    import org.jetbrains.kotlin.types.ErrorUtils;
041    import org.jetbrains.kotlin.types.JetType;
042    import org.jetbrains.kotlin.types.LazyType;
043    import org.jetbrains.kotlin.types.TypeConstructor;
044    import org.jetbrains.kotlin.types.checker.JetTypeChecker;
045    
046    import java.util.*;
047    
048    import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isAny;
049    import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.*;
050    import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage.getBuiltIns;
051    
052    public class DescriptorUtils {
053        public static final Name ENUM_VALUES = Name.identifier("values");
054        public static final Name ENUM_VALUE_OF = Name.identifier("valueOf");
055        public static final FqName JVM_NAME = new FqName("kotlin.jvm.JvmName");
056        public static final FqName PLATFORM_NAME = new FqName("kotlin.platform.platformName");
057    
058        private DescriptorUtils() {
059        }
060    
061        @Nullable
062        public static ReceiverParameterDescriptor getDispatchReceiverParameterIfNeeded(@NotNull DeclarationDescriptor containingDeclaration) {
063            if (containingDeclaration instanceof ClassDescriptor) {
064                ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
065                return classDescriptor.getThisAsReceiverParameter();
066            }
067            else if (containingDeclaration instanceof ScriptDescriptor) {
068                ScriptDescriptor scriptDescriptor = (ScriptDescriptor) containingDeclaration;
069                return scriptDescriptor.getThisAsReceiverParameter();
070            }
071            return null;
072        }
073    
074        /**
075         * Descriptor may be local itself or have a local ancestor
076         */
077        public static boolean isLocal(@NotNull DeclarationDescriptor descriptor) {
078            DeclarationDescriptor current = descriptor;
079            while (current != null) {
080                if (isAnonymousObject(current) || isDescriptorWithLocalVisibility(current)) {
081                    return true;
082                }
083                current = current.getContainingDeclaration();
084            }
085            return false;
086        }
087    
088        private static boolean isDescriptorWithLocalVisibility(DeclarationDescriptor current) {
089            return current instanceof DeclarationDescriptorWithVisibility &&
090             ((DeclarationDescriptorWithVisibility) current).getVisibility() == Visibilities.LOCAL;
091        }
092    
093        @NotNull
094        public static FqNameUnsafe getFqName(@NotNull DeclarationDescriptor descriptor) {
095            FqName safe = getFqNameSafeIfPossible(descriptor);
096            return safe != null ? safe.toUnsafe() : getFqNameUnsafe(descriptor);
097        }
098    
099        @NotNull
100        public static FqName getFqNameSafe(@NotNull DeclarationDescriptor descriptor) {
101            FqName safe = getFqNameSafeIfPossible(descriptor);
102            return safe != null ? safe : getFqNameUnsafe(descriptor).toSafe();
103        }
104    
105    
106        @Nullable
107        private static FqName getFqNameSafeIfPossible(@NotNull DeclarationDescriptor descriptor) {
108            if (descriptor instanceof ModuleDescriptor || ErrorUtils.isError(descriptor)) {
109                return FqName.ROOT;
110            }
111    
112            if (descriptor instanceof PackageViewDescriptor) {
113                return ((PackageViewDescriptor) descriptor).getFqName();
114            }
115            else if (descriptor instanceof PackageFragmentDescriptor) {
116                return ((PackageFragmentDescriptor) descriptor).getFqName();
117            }
118    
119            return null;
120        }
121    
122        @NotNull
123        private static FqNameUnsafe getFqNameUnsafe(@NotNull DeclarationDescriptor descriptor) {
124            DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
125            assert containingDeclaration != null : "Not package/module descriptor doesn't have containing declaration: " + descriptor;
126            return getFqName(containingDeclaration).child(descriptor.getName());
127        }
128    
129        @NotNull
130        public static FqName getFqNameFromTopLevelClass(@NotNull DeclarationDescriptor descriptor) {
131            DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
132            Name name = descriptor.getName();
133            if (!(containingDeclaration instanceof ClassDescriptor)) {
134                return FqName.topLevel(name);
135            }
136            return getFqNameFromTopLevelClass(containingDeclaration).child(name);
137        }
138    
139        public static boolean isTopLevelDeclaration(@NotNull DeclarationDescriptor descriptor) {
140            return descriptor.getContainingDeclaration() instanceof PackageFragmentDescriptor;
141        }
142    
143        public static boolean isExtension(@NotNull CallableDescriptor descriptor) {
144            return (descriptor.getExtensionReceiverParameter() != null);
145        }
146    
147        public static boolean isOverride(@NotNull CallableMemberDescriptor descriptor) {
148            return !descriptor.getOverriddenDescriptors().isEmpty();
149        }
150    
151        /**
152         * @return true iff this is a top-level declaration or a class member with no expected "this" object (e.g. static members in Java,
153         * values() and valueOf() methods of enum classes, etc.)
154         */
155        public static boolean isStaticDeclaration(@NotNull CallableDescriptor descriptor) {
156            if (descriptor instanceof ConstructorDescriptor) return false;
157    
158            DeclarationDescriptor container = descriptor.getContainingDeclaration();
159            return container instanceof PackageFragmentDescriptor ||
160                   (container instanceof ClassDescriptor && descriptor.getDispatchReceiverParameter() == null);
161        }
162    
163        // WARNING! Don't use this method in JVM backend, use JvmCodegenUtil.isCallInsideSameModuleAsDeclared() instead.
164        // The latter handles compilation against compiled part of our module correctly.
165        public static boolean areInSameModule(@NotNull DeclarationDescriptor first, @NotNull DeclarationDescriptor second) {
166            return getContainingModule(first).equals(getContainingModule(second));
167        }
168    
169        @Nullable
170        public static <D extends DeclarationDescriptor> D getParentOfType(
171                @Nullable DeclarationDescriptor descriptor,
172                @NotNull Class<D> aClass
173        ) {
174            return getParentOfType(descriptor, aClass, true);
175        }
176    
177        @Nullable
178        public static <D extends DeclarationDescriptor> D getParentOfType(
179                @Nullable DeclarationDescriptor descriptor,
180                @NotNull Class<D> aClass,
181                boolean strict
182        ) {
183            if (descriptor == null) return null;
184            if (strict) {
185                descriptor = descriptor.getContainingDeclaration();
186            }
187            while (descriptor != null) {
188                if (aClass.isInstance(descriptor)) {
189                    //noinspection unchecked
190                    return (D) descriptor;
191                }
192                descriptor = descriptor.getContainingDeclaration();
193            }
194            return null;
195        }
196    
197        @NotNull
198        public static ModuleDescriptor getContainingModule(@NotNull DeclarationDescriptor descriptor) {
199            ModuleDescriptor module = getContainingModuleOrNull(descriptor);
200            assert module != null : "Descriptor without a containing module: " + descriptor;
201            return module;
202        }
203    
204        @Nullable
205        public static ModuleDescriptor getContainingModuleOrNull(@NotNull DeclarationDescriptor descriptor) {
206            while (descriptor != null) {
207                if (descriptor instanceof ModuleDescriptor) {
208                    return (ModuleDescriptor) descriptor;
209                }
210                if (descriptor instanceof PackageViewDescriptor) {
211                    return ((PackageViewDescriptor) descriptor).getModule();
212                }
213                descriptor = descriptor.getContainingDeclaration();
214            }
215            return null;
216        }
217    
218        @Nullable
219        public static ClassDescriptor getContainingClass(@NotNull DeclarationDescriptor descriptor) {
220            DeclarationDescriptor containing = descriptor.getContainingDeclaration();
221            while (containing != null) {
222                if (containing instanceof ClassDescriptor && !isCompanionObject(containing)) {
223                    return (ClassDescriptor) containing;
224                }
225                containing = containing.getContainingDeclaration();
226            }
227            return null;
228        }
229    
230        public static boolean isAncestor(
231                @Nullable DeclarationDescriptor ancestor,
232                @NotNull DeclarationDescriptor declarationDescriptor,
233                boolean strict
234        ) {
235            if (ancestor == null) return false;
236            DeclarationDescriptor descriptor = strict ? declarationDescriptor.getContainingDeclaration() : declarationDescriptor;
237            while (descriptor != null) {
238                if (ancestor == descriptor) return true;
239                descriptor = descriptor.getContainingDeclaration();
240            }
241            return false;
242        }
243    
244        public static boolean isDirectSubclass(@NotNull ClassDescriptor subClass, @NotNull ClassDescriptor superClass) {
245            for (JetType superType : subClass.getTypeConstructor().getSupertypes()) {
246                if (isSameClass(superType, superClass.getOriginal())) {
247                    return true;
248                }
249            }
250            return false;
251        }
252    
253        public static boolean isSubclass(@NotNull ClassDescriptor subClass, @NotNull ClassDescriptor superClass) {
254            return isSubtypeOfClass(subClass.getDefaultType(), superClass.getOriginal());
255        }
256    
257        private static boolean isSameClass(@NotNull JetType type, @NotNull DeclarationDescriptor other) {
258            DeclarationDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
259            if (descriptor != null) {
260                DeclarationDescriptor originalDescriptor = descriptor.getOriginal();
261                if (originalDescriptor instanceof ClassifierDescriptor
262                    && other instanceof ClassifierDescriptor
263                    && ((ClassifierDescriptor) other).getTypeConstructor().equals(
264                        ((ClassifierDescriptor) originalDescriptor).getTypeConstructor())) {
265                    return true;
266                }
267            }
268            return false;
269        }
270    
271        private static boolean isSubtypeOfClass(@NotNull JetType type, @NotNull DeclarationDescriptor superClass) {
272            if (isSameClass(type, superClass)) return true;
273            for (JetType superType : type.getConstructor().getSupertypes()) {
274                if (isSubtypeOfClass(superType, superClass)) {
275                    return true;
276                }
277            }
278            return false;
279        }
280    
281        public static boolean isFunctionLiteral(@Nullable DeclarationDescriptor descriptor) {
282            return descriptor instanceof AnonymousFunctionDescriptor;
283        }
284    
285        public static boolean isLocalFunction(@Nullable DeclarationDescriptor descriptor) {
286            if (descriptor != null && descriptor.getClass() == SimpleFunctionDescriptorImpl.class) {
287                return ((SimpleFunctionDescriptorImpl) descriptor).getVisibility() == Visibilities.LOCAL;
288            }
289            return false;
290        }
291    
292        public static boolean isFunctionExpression(@Nullable DeclarationDescriptor descriptor) {
293            return descriptor instanceof FunctionExpressionDescriptor;
294        }
295    
296        public static boolean isCompanionObject(@Nullable DeclarationDescriptor descriptor) {
297            return isKindOf(descriptor, ClassKind.OBJECT) && ((ClassDescriptor) descriptor).isCompanionObject();
298        }
299    
300        public static boolean isAnonymousObject(@NotNull DeclarationDescriptor descriptor) {
301            return isClass(descriptor) && descriptor.getName().equals(SpecialNames.NO_NAME_PROVIDED);
302        }
303    
304        public static boolean isNonCompanionObject(@NotNull DeclarationDescriptor descriptor) {
305            return isKindOf(descriptor, ClassKind.OBJECT) && !((ClassDescriptor) descriptor).isCompanionObject();
306        }
307    
308        public static boolean isObject(@NotNull DeclarationDescriptor descriptor) {
309            return isKindOf(descriptor, ClassKind.OBJECT);
310        }
311    
312        public static boolean isEnumEntry(@NotNull DeclarationDescriptor descriptor) {
313            return isKindOf(descriptor, ClassKind.ENUM_ENTRY);
314        }
315    
316        public static boolean isSingleton(@Nullable DeclarationDescriptor classifier) {
317            if (classifier instanceof ClassDescriptor) {
318                ClassDescriptor clazz = (ClassDescriptor) classifier;
319                return clazz.getKind().isSingleton();
320            }
321            return false;
322        }
323    
324        public static boolean isEnumClass(@Nullable DeclarationDescriptor descriptor) {
325            return isKindOf(descriptor, ClassKind.ENUM_CLASS);
326        }
327    
328        public static boolean isAnnotationClass(@Nullable DeclarationDescriptor descriptor) {
329            return isKindOf(descriptor, ClassKind.ANNOTATION_CLASS);
330        }
331    
332        public static boolean isTrait(@Nullable DeclarationDescriptor descriptor) {
333            return isKindOf(descriptor, ClassKind.INTERFACE);
334        }
335    
336        public static boolean isClass(@Nullable DeclarationDescriptor descriptor) {
337            return isKindOf(descriptor, ClassKind.CLASS);
338        }
339    
340        private static boolean isKindOf(@Nullable DeclarationDescriptor descriptor, @NotNull ClassKind classKind) {
341            return descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).getKind() == classKind;
342        }
343    
344        @NotNull
345        public static List<ClassDescriptor> getSuperclassDescriptors(@NotNull ClassDescriptor classDescriptor) {
346            Collection<JetType> superclassTypes = classDescriptor.getTypeConstructor().getSupertypes();
347            List<ClassDescriptor> superClassDescriptors = new ArrayList<ClassDescriptor>();
348            for (JetType type : superclassTypes) {
349                ClassDescriptor result = getClassDescriptorForType(type);
350                if (!isAny(result)) {
351                    superClassDescriptors.add(result);
352                }
353            }
354            return superClassDescriptors;
355        }
356    
357        @NotNull
358        public static JetType getSuperClassType(@NotNull ClassDescriptor classDescriptor) {
359            Collection<JetType> superclassTypes = classDescriptor.getTypeConstructor().getSupertypes();
360            for (JetType type : superclassTypes) {
361                ClassDescriptor superClassDescriptor = getClassDescriptorForType(type);
362                if (superClassDescriptor.getKind() != ClassKind.INTERFACE) {
363                    return type;
364                }
365            }
366            return getBuiltIns(classDescriptor).getAnyType();
367        }
368    
369        @NotNull
370        public static ClassDescriptor getClassDescriptorForType(@NotNull JetType type) {
371            return getClassDescriptorForTypeConstructor(type.getConstructor());
372        }
373    
374        @NotNull
375        public static ClassDescriptor getClassDescriptorForTypeConstructor(@NotNull TypeConstructor typeConstructor) {
376            ClassifierDescriptor descriptor = typeConstructor.getDeclarationDescriptor();
377            assert descriptor instanceof ClassDescriptor
378                : "Classifier descriptor of a type should be of type ClassDescriptor: " + typeConstructor;
379            return (ClassDescriptor) descriptor;
380        }
381    
382        @NotNull
383        public static Visibility getDefaultConstructorVisibility(@NotNull ClassDescriptor classDescriptor) {
384            ClassKind classKind = classDescriptor.getKind();
385            if (classKind == ClassKind.ENUM_CLASS || classKind.isSingleton() || classDescriptor.getModality() == Modality.SEALED) {
386                return Visibilities.PRIVATE;
387            }
388            if (isAnonymousObject(classDescriptor)) {
389                return Visibilities.DEFAULT_VISIBILITY;
390            }
391            assert classKind == ClassKind.CLASS || classKind == ClassKind.INTERFACE || classKind == ClassKind.ANNOTATION_CLASS;
392            return Visibilities.PUBLIC;
393        }
394    
395        // TODO: should be internal
396        @Nullable
397        public static ClassDescriptor getInnerClassByName(@NotNull ClassDescriptor classDescriptor, @NotNull String innerClassName, @NotNull LookupLocation location) {
398            ClassifierDescriptor classifier =
399                    classDescriptor.getDefaultType().getMemberScope().getClassifier(Name.identifier(innerClassName), location);
400            assert classifier instanceof ClassDescriptor :
401                    "Inner class " + innerClassName + " in " + classDescriptor + " should be instance of ClassDescriptor, but was: "
402                    + (classifier == null ? "null" : classifier.getClass());
403            return (ClassDescriptor) classifier;
404        }
405    
406        @Nullable
407        public static JetType getReceiverParameterType(@Nullable ReceiverParameterDescriptor receiverParameterDescriptor) {
408            return receiverParameterDescriptor == null ? null : receiverParameterDescriptor.getType();
409        }
410    
411        /**
412         * @return true if descriptor is a class inside another class and does not have access to the outer class
413         */
414        public static boolean isStaticNestedClass(@NotNull DeclarationDescriptor descriptor) {
415            DeclarationDescriptor containing = descriptor.getContainingDeclaration();
416            return descriptor instanceof ClassDescriptor &&
417                   containing instanceof ClassDescriptor &&
418                   !((ClassDescriptor) descriptor).isInner();
419        }
420    
421        @NotNull
422        public static JetScope getStaticNestedClassesScope(@NotNull ClassDescriptor descriptor) {
423            JetScope innerClassesScope = descriptor.getUnsubstitutedInnerClassesScope();
424            return new FilteringScope(innerClassesScope, new Function1<DeclarationDescriptor, Boolean>() {
425                @Override
426                public Boolean invoke(DeclarationDescriptor descriptor) {
427                    return descriptor instanceof ClassDescriptor && !((ClassDescriptor) descriptor).isInner();
428                }
429            });
430        }
431    
432        /**
433         * @return true iff {@code descriptor}'s first non-class container is a package
434         */
435        public static boolean isTopLevelOrInnerClass(@NotNull ClassDescriptor descriptor) {
436            DeclarationDescriptor containing = descriptor.getContainingDeclaration();
437            return isTopLevelDeclaration(descriptor) ||
438                   containing instanceof ClassDescriptor && isTopLevelOrInnerClass((ClassDescriptor) containing);
439        }
440    
441        /**
442         * Given a fake override, finds any declaration of it in the overridden descriptors. Keep in mind that there may be many declarations
443         * of the fake override in the supertypes, this method finds just the only one.
444         * TODO: probably all call-sites of this method are wrong, they should handle all super-declarations
445         */
446        @NotNull
447        public static <D extends CallableMemberDescriptor> D unwrapFakeOverride(@NotNull D descriptor) {
448            while (descriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
449                Collection<? extends CallableMemberDescriptor> overridden = descriptor.getOverriddenDescriptors();
450                if (overridden.isEmpty()) {
451                    throw new IllegalStateException("Fake override should have at least one overridden descriptor: " + descriptor);
452                }
453                //noinspection unchecked
454                descriptor = (D) overridden.iterator().next();
455            }
456            return descriptor;
457        }
458    
459        public static boolean shouldRecordInitializerForProperty(@NotNull VariableDescriptor variable, @NotNull JetType type) {
460            if (variable.isVar() || type.isError()) return false;
461    
462            if (type instanceof LazyType || type.isMarkedNullable()) return true;
463    
464            KotlinBuiltIns builtIns = getBuiltIns(variable);
465            return KotlinBuiltIns.isPrimitiveType(type) ||
466                   JetTypeChecker.DEFAULT.equalTypes(builtIns.getStringType(), type) ||
467                   JetTypeChecker.DEFAULT.equalTypes(builtIns.getNumber().getDefaultType(), type) ||
468                   JetTypeChecker.DEFAULT.equalTypes(builtIns.getAnyType(), type);
469        }
470    
471        public static boolean classCanHaveAbstractMembers(@NotNull ClassDescriptor classDescriptor) {
472            return classDescriptor.getModality() == Modality.ABSTRACT
473                   || classDescriptor.getModality() == Modality.SEALED
474                   || classDescriptor.getKind() == ClassKind.ENUM_CLASS;
475        }
476    
477        public static boolean classCanHaveOpenMembers(@NotNull ClassDescriptor classDescriptor) {
478            return classDescriptor.getModality() != Modality.FINAL || classDescriptor.getKind() == ClassKind.ENUM_CLASS;
479        }
480    
481        @NotNull
482        @SuppressWarnings("unchecked")
483        public static <D extends CallableDescriptor> Set<D> getAllOverriddenDescriptors(@NotNull D f) {
484            Set<D> result = new LinkedHashSet<D>();
485            collectAllOverriddenDescriptors((D) f.getOriginal(), result);
486            return result;
487        }
488    
489        private static <D extends CallableDescriptor> void collectAllOverriddenDescriptors(@NotNull D current, @NotNull Set<D> result) {
490            if (result.contains(current)) return;
491            for (CallableDescriptor callableDescriptor : current.getOriginal().getOverriddenDescriptors()) {
492                @SuppressWarnings("unchecked")
493                D descriptor = (D) callableDescriptor;
494                collectAllOverriddenDescriptors(descriptor, result);
495                result.add(descriptor);
496            }
497        }
498    
499        @NotNull
500        public static <D extends CallableMemberDescriptor> Set<D> getAllOverriddenDeclarations(@NotNull D memberDescriptor) {
501            Set<D> result = new HashSet<D>();
502            for (CallableMemberDescriptor overriddenDeclaration : memberDescriptor.getOverriddenDescriptors()) {
503                CallableMemberDescriptor.Kind kind = overriddenDeclaration.getKind();
504                if (kind == DECLARATION) {
505                    //noinspection unchecked
506                    result.add((D) overriddenDeclaration);
507                }
508                else if (kind == DELEGATION || kind == FAKE_OVERRIDE || kind == SYNTHESIZED) {
509                    //do nothing
510                }
511                else {
512                    throw new AssertionError("Unexpected callable kind " + kind);
513                }
514                //noinspection unchecked
515                result.addAll(getAllOverriddenDeclarations((D) overriddenDeclaration));
516            }
517            return result;
518        }
519    
520        public static boolean containsReifiedTypeParameterWithName(@NotNull CallableDescriptor descriptor, @NotNull String name) {
521            for (TypeParameterDescriptor typeParameterDescriptor : descriptor.getTypeParameters()) {
522                if (typeParameterDescriptor.isReified() && typeParameterDescriptor.getName().asString().equals(name)) return true;
523            }
524    
525            return false;
526        }
527    
528        public static boolean containsReifiedTypeParameters(@NotNull CallableDescriptor descriptor) {
529            for (TypeParameterDescriptor typeParameterDescriptor : descriptor.getTypeParameters()) {
530                if (typeParameterDescriptor.isReified()) return true;
531            }
532    
533            return false;
534        }
535    
536        public static boolean isSingletonOrAnonymousObject(@NotNull ClassDescriptor classDescriptor) {
537            return classDescriptor.getKind().isSingleton() || isAnonymousObject(classDescriptor);
538        }
539    
540        public static boolean canHaveDeclaredConstructors(@NotNull ClassDescriptor classDescriptor) {
541            return !isSingletonOrAnonymousObject(classDescriptor) && !isTrait(classDescriptor);
542        }
543    
544        public static boolean hasDefaultConstructor(@NotNull ClassDescriptor classDescriptor) {
545            for (ConstructorDescriptor constructor : classDescriptor.getConstructors()) {
546                if (constructor.getValueParameters().isEmpty()) return true;
547            }
548            return false;
549        }
550    
551        public static Set<FqName> getPackagesFqNames(ModuleDescriptor module) {
552            Set<FqName> result = getSubPackagesFqNames(module.getPackage(FqName.ROOT));
553            result.add(FqName.ROOT);
554            return result;
555        }
556    
557        public static Set<FqName> getSubPackagesFqNames(PackageViewDescriptor packageView) {
558            Set<FqName> result = new HashSet<FqName>();
559            getSubPackagesFqNames(packageView, result);
560    
561            return result;
562        }
563    
564        @Nullable
565        public static String getJvmName(@NotNull Annotated annotated) {
566            AnnotationDescriptor jvmNameAnnotation = getJvmNameAnnotation(annotated.getAnnotations());
567            if (jvmNameAnnotation == null) return null;
568    
569            Map<ValueParameterDescriptor, ConstantValue<?>> arguments = jvmNameAnnotation.getAllValueArguments();
570            if (arguments.isEmpty()) return null;
571    
572            ConstantValue<?> name = arguments.values().iterator().next();
573            if (!(name instanceof StringValue)) return null;
574    
575            return ((StringValue) name).getValue();
576        }
577    
578        @Nullable
579        public static AnnotationDescriptor getJvmNameAnnotation(@NotNull Annotations annotations) {
580            AnnotationDescriptor jvmNameAnnotation = annotations.findAnnotation(JVM_NAME);
581            if (jvmNameAnnotation == null) {
582                jvmNameAnnotation = annotations.findAnnotation(PLATFORM_NAME);
583            }
584            return jvmNameAnnotation;
585        }
586    
587        @Nullable
588        public static AnnotationDescriptor getJvmNameAnnotation(@NotNull Annotated annotated) {
589            return getJvmNameAnnotation(annotated.getAnnotations());
590        }
591    
592        private static void getSubPackagesFqNames(PackageViewDescriptor packageView, Set<FqName> result) {
593            FqName fqName = packageView.getFqName();
594            if (!fqName.isRoot()) {
595                result.add(fqName);
596            }
597    
598            for (DeclarationDescriptor descriptor : packageView.getMemberScope().getDescriptors(DescriptorKindFilter.PACKAGES, JetScope.ALL_NAME_FILTER)) {
599                if (descriptor instanceof PackageViewDescriptor) {
600                    getSubPackagesFqNames((PackageViewDescriptor) descriptor, result);
601                }
602            }
603        }
604    }