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