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