001    /*
002     * Copyright 2010-2013 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.jet.lang.resolve;
018    
019    import com.google.common.collect.Lists;
020    import com.google.common.collect.Maps;
021    import com.google.common.collect.Sets;
022    import com.intellij.psi.PsiElement;
023    import com.intellij.util.Function;
024    import com.intellij.util.containers.ContainerUtil;
025    import com.intellij.util.containers.LinkedMultiMap;
026    import com.intellij.util.containers.MultiMap;
027    import com.intellij.util.containers.hash.EqualityPolicy;
028    import kotlin.Function1;
029    import kotlin.Unit;
030    import org.jetbrains.annotations.NotNull;
031    import org.jetbrains.annotations.Nullable;
032    import org.jetbrains.annotations.ReadOnly;
033    import org.jetbrains.jet.lang.descriptors.*;
034    import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
035    import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
036    import org.jetbrains.jet.lang.psi.*;
037    import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil;
038    import org.jetbrains.jet.lang.resolve.name.Name;
039    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
040    import org.jetbrains.jet.lang.types.*;
041    import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
042    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
043    import org.jetbrains.jet.lexer.JetTokens;
044    import org.jetbrains.jet.utils.HashSetUtil;
045    
046    import javax.inject.Inject;
047    import java.util.*;
048    
049    import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.*;
050    import static org.jetbrains.jet.lang.diagnostics.Errors.*;
051    import static org.jetbrains.jet.lang.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE;
052    
053    public class OverrideResolver {
054    
055        private BindingTrace trace;
056    
057        @Inject
058        public void setTrace(BindingTrace trace) {
059            this.trace = trace;
060        }
061    
062    
063    
064        public void process(@NotNull TopDownAnalysisContext c) {
065            //all created fake descriptors are stored to resolve visibility on them later
066            generateOverridesAndDelegation(c);
067    
068            check(c);
069        }
070    
071        public void check(@NotNull TopDownAnalysisContext c) {
072            checkVisibility(c);
073            checkOverrides(c);
074            checkParameterOverridesForAllClasses(c);
075        }
076    
077        /**
078         * Generate fake overrides and add overridden descriptors to existing descriptors.
079         */
080        private void generateOverridesAndDelegation(@NotNull TopDownAnalysisContext c) {
081            Set<ClassDescriptorWithResolutionScopes> ourClasses = new HashSet<ClassDescriptorWithResolutionScopes>(c.getAllClasses());
082            Set<ClassifierDescriptor> processed = new HashSet<ClassifierDescriptor>();
083    
084            for (MutableClassDescriptor klass : ContainerUtil.reverse(c.getClassesTopologicalOrder())) {
085                if (ourClasses.contains(klass)) {
086                    generateOverridesAndDelegationInAClass(klass, processed, ourClasses);
087    
088                    MutableClassDescriptor classObject = klass.getClassObjectDescriptor();
089                    if (classObject != null) {
090                        generateOverridesAndDelegationInAClass(classObject, processed, ourClasses);
091                    }
092                }
093            }
094        }
095    
096        private void generateOverridesAndDelegationInAClass(
097                @NotNull MutableClassDescriptor classDescriptor,
098                @NotNull Set<ClassifierDescriptor> processed,
099                @NotNull Set<ClassDescriptorWithResolutionScopes> classesBeingAnalyzed
100                // to filter out classes such as stdlib and others that come from dependencies
101        ) {
102            if (!processed.add(classDescriptor)) {
103                return;
104            }
105    
106            for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
107                ClassDescriptor superclass = (ClassDescriptor) supertype.getConstructor().getDeclarationDescriptor();
108                if (superclass instanceof MutableClassDescriptor && classesBeingAnalyzed.contains(superclass)) {
109                    generateOverridesAndDelegationInAClass((MutableClassDescriptor) superclass, processed, classesBeingAnalyzed);
110                }
111            }
112    
113            JetClassOrObject classOrObject = (JetClassOrObject) BindingContextUtils
114                    .classDescriptorToDeclaration(trace.getBindingContext(), classDescriptor);
115            if (classOrObject != null) {
116                DelegationResolver.generateDelegatesInAClass(classDescriptor, trace, classOrObject);
117            }
118    
119            generateOverridesInAClass(classDescriptor);
120        }
121    
122        private void generateOverridesInAClass(@NotNull final MutableClassDescriptor classDescriptor) {
123            List<CallableMemberDescriptor> membersFromSupertypes = getCallableMembersFromSupertypes(classDescriptor);
124    
125            MultiMap<Name, CallableMemberDescriptor> membersFromSupertypesByName = groupDescriptorsByName(membersFromSupertypes);
126    
127            MultiMap<Name, CallableMemberDescriptor> membersFromCurrentByName = groupDescriptorsByName(classDescriptor.getDeclaredCallableMembers());
128    
129            Set<Name> memberNames = new LinkedHashSet<Name>();
130            memberNames.addAll(membersFromSupertypesByName.keySet());
131            memberNames.addAll(membersFromCurrentByName.keySet());
132    
133            for (Name memberName : memberNames) {
134                Collection<CallableMemberDescriptor> fromSupertypes = membersFromSupertypesByName.get(memberName);
135                Collection<CallableMemberDescriptor> fromCurrent = membersFromCurrentByName.get(memberName);
136    
137                OverridingUtil.generateOverridesInFunctionGroup(
138                        memberName,
139                        fromSupertypes,
140                        fromCurrent,
141                        classDescriptor,
142                        new OverridingUtil.DescriptorSink() {
143                            @Override
144                            public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
145                                if (fakeOverride instanceof PropertyDescriptor) {
146                                    classDescriptor.getBuilder().addPropertyDescriptor((PropertyDescriptor) fakeOverride);
147                                }
148                                else if (fakeOverride instanceof SimpleFunctionDescriptor) {
149                                    classDescriptor.getBuilder().addFunctionDescriptor((SimpleFunctionDescriptor) fakeOverride);
150                                }
151                                else {
152                                    throw new IllegalStateException(fakeOverride.getClass().getName());
153                                }
154                            }
155    
156                            @Override
157                            public void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent) {
158                                JetDeclaration declaration =
159                                        (JetDeclaration) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), fromCurrent);
160                                //noinspection ConstantConditions
161                                trace.report(CONFLICTING_OVERLOADS.on(declaration, fromCurrent, fromCurrent.getContainingDeclaration().getName().asString()));
162                            }
163                        });
164            }
165            resolveUnknownVisibilities(classDescriptor.getAllCallableMembers(), trace);
166        }
167    
168        public static void resolveUnknownVisibilities(
169                @NotNull Collection<? extends CallableMemberDescriptor> descriptors,
170                @NotNull BindingTrace trace
171        ) {
172            for (CallableMemberDescriptor descriptor : descriptors) {
173                OverridingUtil.resolveUnknownVisibilityForMember(descriptor, createCannotInferVisibilityReporter(trace));
174            }
175        }
176    
177        @NotNull
178        public static Function1<CallableMemberDescriptor, Unit> createCannotInferVisibilityReporter(@NotNull final BindingTrace trace) {
179            return new Function1<CallableMemberDescriptor, Unit>() {
180                @Override
181                public Unit invoke(@NotNull CallableMemberDescriptor descriptor) {
182                    DeclarationDescriptor reportOn;
183                    if (descriptor.getKind() == FAKE_OVERRIDE || descriptor.getKind() == DELEGATION) {
184                        reportOn = DescriptorUtils.getParentOfType(descriptor, ClassDescriptor.class);
185                    }
186                    else if (descriptor instanceof PropertyAccessorDescriptor && ((PropertyAccessorDescriptor) descriptor).isDefault()) {
187                        reportOn = ((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty();
188                    }
189                    else {
190                        reportOn = descriptor;
191                    }
192                    //noinspection ConstantConditions
193                    PsiElement element = BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), reportOn);
194                    if (element instanceof JetDeclaration) {
195                        trace.report(CANNOT_INFER_VISIBILITY.on((JetDeclaration) element, descriptor));
196                    }
197                    return Unit.VALUE;
198                }
199            };
200        }
201    
202        private static enum Filtering {
203            RETAIN_OVERRIDING,
204            RETAIN_OVERRIDDEN
205        }
206    
207        @NotNull
208        public static <D extends CallableDescriptor> Set<D> filterOutOverridden(@NotNull Set<D> candidateSet) {
209            //noinspection unchecked
210            return filterOverrides(candidateSet, Function.ID, Filtering.RETAIN_OVERRIDING);
211        }
212    
213        @NotNull
214        public static <D> Set<D> filterOutOverriding(@NotNull Set<D> candidateSet) {
215            //noinspection unchecked
216            return filterOverrides(candidateSet, Function.ID, Filtering.RETAIN_OVERRIDDEN);
217        }
218    
219        @NotNull
220        public static <D> Set<D> filterOutOverridden(
221                @NotNull Set<D> candidateSet,
222                @NotNull Function<? super D, ? extends CallableDescriptor> transform
223        ) {
224            return filterOverrides(candidateSet, transform, Filtering.RETAIN_OVERRIDING);
225        }
226    
227        @NotNull
228        private static <D> Set<D> filterOverrides(
229                @NotNull Set<D> candidateSet,
230                @NotNull final Function<? super D, ? extends CallableDescriptor> transform,
231                @NotNull Filtering filtering
232        ) {
233            if (candidateSet.size() <= 1) return candidateSet;
234    
235            // In a multi-module project different "copies" of the same class may be present in different libraries,
236            // that's why we use structural equivalence for members (DescriptorEquivalenceForOverrides).
237            // Here we filter out structurally equivalent descriptors before processing overrides, because such descriptors
238            // "override" each other (overrides(f, g) = overrides(g, f) = true) and the code below removes them all from the
239            // candidates, unless we first compute noDuplicates
240            Set<D> noDuplicates = HashSetUtil.linkedHashSet(
241                    candidateSet,
242                    new EqualityPolicy<D>() {
243                        @Override
244                        public int getHashCode(D d) {
245                            return DescriptorUtils.getFqName(transform.fun(d).getContainingDeclaration()).hashCode();
246                        }
247    
248                        @Override
249                        public boolean isEqual(D d1, D d2) {
250                            CallableDescriptor f = transform.fun(d1);
251                            CallableDescriptor g = transform.fun(d2);
252                            return DescriptorEquivalenceForOverrides.instance$.areEquivalent(f.getOriginal(), g.getOriginal());
253                        }
254                    });
255    
256            Set<D> candidates = Sets.newLinkedHashSet();
257            outerLoop:
258            for (D meD : noDuplicates) {
259                CallableDescriptor me = transform.fun(meD);
260                for (D otherD : noDuplicates) {
261                    CallableDescriptor other = transform.fun(otherD);
262                    if (me == other) continue;
263                    if (filtering == Filtering.RETAIN_OVERRIDING) {
264                        if (overrides(other, me)) {
265                            continue outerLoop;
266                        }
267                    }
268                    else if (filtering == Filtering.RETAIN_OVERRIDDEN) {
269                        if (overrides(me, other)) {
270                            continue outerLoop;
271                        }
272                    }
273                    else {
274                        throw new AssertionError("Unexpected Filtering object: " + filtering);
275                    }
276                }
277                for (D otherD : candidates) {
278                    CallableDescriptor other = transform.fun(otherD);
279                    if (me.getOriginal() == other.getOriginal()
280                        && OverridingUtil.DEFAULT.isOverridableBy(other, me).getResult() == OVERRIDABLE
281                        && OverridingUtil.DEFAULT.isOverridableBy(me, other).getResult() == OVERRIDABLE) {
282                        continue outerLoop;
283                    }
284                }
285                candidates.add(meD);
286            }
287    
288            assert !candidates.isEmpty() : "All candidates filtered out from " + candidateSet;
289    
290            return candidates;
291        }
292    
293        // check whether f overrides g
294        public static <D extends CallableDescriptor> boolean overrides(@NotNull D f, @NotNull D g) {
295            // This first check cover the case of duplicate classes in different modules:
296            // when B is defined in modules m1 and m2, and C (indirectly) inherits from both versions,
297            // we'll be getting sets of members that do not override each other, but are structurally equivalent.
298            // As other code relies on no equal descriptors passed here, we guard against f == g, but this may not be necessary
299            if (!f.equals(g) && DescriptorEquivalenceForOverrides.instance$.areEquivalent(f.getOriginal(), g.getOriginal())) return true;
300            CallableDescriptor originalG = g.getOriginal();
301            for (D overriddenFunction : getAllOverriddenDescriptors(f)) {
302                if (DescriptorEquivalenceForOverrides.instance$.areEquivalent(originalG, overriddenFunction.getOriginal())) return true;
303            }
304            return false;
305        }
306    
307        @NotNull
308        @SuppressWarnings("unchecked")
309        public static <D extends CallableDescriptor> Set<D> getAllOverriddenDescriptors(@NotNull D f) {
310            Set<D> result = new LinkedHashSet<D>();
311            collectAllOverriddenDescriptors((D) f.getOriginal(), result);
312            return result;
313        }
314    
315        private static <D extends CallableDescriptor> void collectAllOverriddenDescriptors(@NotNull D current, @NotNull Set<D> result) {
316            if (result.contains(current)) return;
317            for (CallableDescriptor callableDescriptor : current.getOriginal().getOverriddenDescriptors()) {
318                @SuppressWarnings("unchecked")
319                D descriptor = (D) callableDescriptor;
320                collectAllOverriddenDescriptors(descriptor, result);
321                result.add(descriptor);
322            }
323        }
324    
325        private static <T extends DeclarationDescriptor> MultiMap<Name, T> groupDescriptorsByName(Collection<T> properties) {
326            MultiMap<Name, T> r = new LinkedMultiMap<Name, T>();
327            for (T property : properties) {
328                r.putValue(property.getName(), property);
329            }
330            return r;
331        }
332    
333    
334        private static List<CallableMemberDescriptor> getCallableMembersFromSupertypes(ClassDescriptor classDescriptor) {
335            Set<CallableMemberDescriptor> r = Sets.newLinkedHashSet();
336            for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
337                r.addAll(getCallableMembersFromType(supertype.getMemberScope()));
338            }
339            return new ArrayList<CallableMemberDescriptor>(r);
340        }
341    
342        private static List<CallableMemberDescriptor> getCallableMembersFromType(JetScope scope) {
343            List<CallableMemberDescriptor> r = Lists.newArrayList();
344            for (DeclarationDescriptor decl : scope.getAllDescriptors()) {
345                if (decl instanceof PropertyDescriptor || decl instanceof SimpleFunctionDescriptor) {
346                    r.add((CallableMemberDescriptor) decl);
347                }
348            }
349            return r;
350        }
351    
352        private void checkOverrides(@NotNull TopDownAnalysisContext c) {
353            for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
354                checkOverridesInAClass(c, entry.getValue(), entry.getKey());
355            }
356        }
357    
358        private void checkOverridesInAClass(@NotNull TopDownAnalysisContext c, @NotNull ClassDescriptorWithResolutionScopes classDescriptor, @NotNull JetClassOrObject klass) {
359            if (c.getTopDownAnalysisParameters().isAnalyzingBootstrapLibrary()) return;
360    
361            // Check overrides for internal consistency
362            for (CallableMemberDescriptor member : classDescriptor.getDeclaredCallableMembers()) {
363                checkOverrideForMember(member);
364            }
365    
366            // Check if everything that must be overridden, actually is
367            // More than one implementation or no implementations at all
368            Set<CallableMemberDescriptor> abstractNoImpl = Sets.newLinkedHashSet();
369            Set<CallableMemberDescriptor> manyImpl = Sets.newLinkedHashSet();
370            collectMissingImplementations(classDescriptor, abstractNoImpl, manyImpl);
371    
372            if (!manyImpl.isEmpty()) {
373                trace.report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(klass, klass, manyImpl.iterator().next()));
374            }
375    
376            if (classDescriptor.getModality() != Modality.ABSTRACT && !abstractNoImpl.isEmpty()) {
377                trace.report(ABSTRACT_MEMBER_NOT_IMPLEMENTED.on(klass, klass, abstractNoImpl.iterator().next()));
378            }
379        }
380    
381        @NotNull
382        public static Set<CallableMemberDescriptor> getMissingImplementations(@NotNull ClassDescriptor classDescriptor) {
383            Set<CallableMemberDescriptor> result = new LinkedHashSet<CallableMemberDescriptor>();
384            collectMissingImplementations(classDescriptor, result, result);
385            return result;
386        }
387    
388        private static void collectMissingImplementations(
389                @NotNull ClassDescriptor classDescriptor,
390                @NotNull Set<CallableMemberDescriptor> abstractNoImpl,
391                @NotNull Set<CallableMemberDescriptor> manyImpl
392        ) {
393            for (DeclarationDescriptor member : classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
394                if (member instanceof CallableMemberDescriptor) {
395                    collectMissingImplementations((CallableMemberDescriptor) member, abstractNoImpl, manyImpl);
396                }
397            }
398        }
399    
400        private static void collectMissingImplementations(
401                @NotNull CallableMemberDescriptor descriptor,
402                @NotNull Set<CallableMemberDescriptor> abstractNoImpl,
403                @NotNull Set<CallableMemberDescriptor> manyImpl
404        ) {
405            if (descriptor.getKind().isReal()) return;
406            if (descriptor.getVisibility() == Visibilities.INVISIBLE_FAKE) return;
407    
408            Collection<? extends CallableMemberDescriptor> directOverridden = descriptor.getOverriddenDescriptors();
409            if (directOverridden.size() == 0) {
410                throw new IllegalStateException("A 'fake override' must override something");
411            }
412    
413            // collects map from the directly overridden descriptor to the set of declarations:
414            // -- if directly overridden is not fake, the set consists of one element: this directly overridden
415            // -- if it's fake, overridden declarations (non-fake) of this descriptor are collected
416            Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenDeclarationsByDirectParent = collectOverriddenDeclarations(directOverridden);
417    
418            List<CallableMemberDescriptor> allOverriddenDeclarations = ContainerUtil.flatten(overriddenDeclarationsByDirectParent.values());
419            Set<CallableMemberDescriptor> allFilteredOverriddenDeclarations = filterOutOverridden(
420                    Sets.newLinkedHashSet(allOverriddenDeclarations));
421    
422            Set<CallableMemberDescriptor> relevantDirectlyOverridden =
423                    getRelevantDirectlyOverridden(overriddenDeclarationsByDirectParent, allFilteredOverriddenDeclarations);
424    
425            List<CallableMemberDescriptor> implementations = collectImplementations(relevantDirectlyOverridden);
426            if (implementations.size() == 1 && isReturnTypeOkForOverride(descriptor, implementations.get(0))) return;
427    
428            List<CallableMemberDescriptor> abstractOverridden = new ArrayList<CallableMemberDescriptor>(allFilteredOverriddenDeclarations.size());
429            List<CallableMemberDescriptor> concreteOverridden = new ArrayList<CallableMemberDescriptor>(allFilteredOverriddenDeclarations.size());
430            filterNotSynthesizedDescriptorsByModality(allFilteredOverriddenDeclarations, abstractOverridden, concreteOverridden);
431    
432            if (implementations.isEmpty()) {
433                abstractNoImpl.addAll(abstractOverridden);
434            }
435            else if (implementations.size() > 1) {
436                manyImpl.addAll(concreteOverridden);
437            }
438            else {
439                abstractNoImpl.addAll(collectAbstractMethodsWithMoreSpecificReturnType(abstractOverridden, implementations.get(0)));
440            }
441        }
442    
443        @NotNull
444        private static List<CallableMemberDescriptor> collectImplementations(@NotNull Set<CallableMemberDescriptor> relevantDirectlyOverridden) {
445            List<CallableMemberDescriptor> result = new ArrayList<CallableMemberDescriptor>(relevantDirectlyOverridden.size());
446            for (CallableMemberDescriptor overriddenDescriptor : relevantDirectlyOverridden) {
447                if (overriddenDescriptor.getModality() != Modality.ABSTRACT) {
448                    result.add(overriddenDescriptor);
449                }
450            }
451            return result;
452        }
453    
454        private static void filterNotSynthesizedDescriptorsByModality(
455                @NotNull Set<CallableMemberDescriptor> allOverriddenDeclarations,
456                @NotNull List<CallableMemberDescriptor> abstractOverridden,
457                @NotNull List<CallableMemberDescriptor> concreteOverridden
458        ) {
459            for (CallableMemberDescriptor overridden : allOverriddenDeclarations) {
460                if (!CallResolverUtil.isOrOverridesSynthesized(overridden)) {
461                    if (overridden.getModality() == Modality.ABSTRACT) {
462                        abstractOverridden.add(overridden);
463                    }
464                    else {
465                        concreteOverridden.add(overridden);
466                    }
467                }
468            }
469        }
470    
471        @NotNull
472        private static List<CallableMemberDescriptor> collectAbstractMethodsWithMoreSpecificReturnType(
473                @NotNull List<CallableMemberDescriptor> abstractOverridden,
474                @NotNull CallableMemberDescriptor implementation
475        ) {
476            List<CallableMemberDescriptor> result = new ArrayList<CallableMemberDescriptor>(abstractOverridden.size());
477            for (CallableMemberDescriptor abstractMember : abstractOverridden) {
478                if (!isReturnTypeOkForOverride(abstractMember, implementation)) {
479                    result.add(abstractMember);
480                }
481            }
482            assert !result.isEmpty() : "Implementation (" + implementation + ") doesn't have the most specific type, " +
483                                       "but none of the other overridden methods does either: " + abstractOverridden;
484            return result;
485        }
486    
487        @NotNull
488        private static Set<CallableMemberDescriptor> getRelevantDirectlyOverridden(
489                @NotNull Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenByParent,
490                @NotNull Set<CallableMemberDescriptor> allFilteredOverriddenDeclarations
491        ) {
492            /* Let the following class hierarchy is declared:
493    
494            trait A { fun foo() = 1 }
495            trait B : A
496            trait C : A
497            trait D : A { override fun foo() = 2 }
498            trait E : B, C, D {}
499    
500            Traits B and C have fake descriptors for function foo.
501            The map 'overriddenByParent' is:
502            { 'foo in B' (fake) -> { 'foo in A' }, 'foo in C' (fake) -> { 'foo in A' }, 'foo in D' -> { 'foo in D'} }
503            This is a map from directly overridden descriptors (functions 'foo' in B, C, D in this example) to the set of declarations (non-fake),
504            that are overridden by this descriptor.
505    
506            The goal is to leave only relevant directly overridden descriptors to count implementations of our fake function on them.
507            In the example above there is no error (trait E inherits only one implementation of 'foo' (from D), because this implementation is more precise).
508            So only 'foo in D' is relevant.
509    
510            Directly overridden descriptor is not relevant if it doesn't add any more appropriate non-fake declarations of the concerned function.
511            More precisely directly overridden descriptor is not relevant if:
512            - it's declaration set is a subset of declaration set for other directly overridden descriptor
513            ('foo in B' is not relevant because it's declaration set is a subset of 'foo in C' function's declaration set)
514            - each member of it's declaration set is overridden by a member of other declaration set
515            ('foo in C' is not relevant, because 'foo in A' is overridden by 'foo in D', so 'foo in A' is not appropriate non-fake declaration for 'foo')
516    
517            For the last condition allFilteredOverriddenDeclarations helps (for the example above it's { 'foo in A' } only): each declaration set
518            is compared with allFilteredOverriddenDeclarations, if they have no intersection, this means declaration set has only functions that
519            are overridden by some other function and corresponding directly overridden descriptor is not relevant.
520            */
521    
522            for (Iterator<Map.Entry<CallableMemberDescriptor, Set<CallableMemberDescriptor>>> iterator =
523                         overriddenByParent.entrySet().iterator(); iterator.hasNext(); ) {
524                if (!isRelevant(iterator.next().getValue(), overriddenByParent.values(), allFilteredOverriddenDeclarations)) {
525                    iterator.remove();
526                }
527            }
528            return overriddenByParent.keySet();
529        }
530    
531        private static boolean isRelevant(
532                @NotNull Set<CallableMemberDescriptor> declarationSet,
533                @NotNull Collection<Set<CallableMemberDescriptor>> allDeclarationSets,
534                @NotNull Set<CallableMemberDescriptor> allFilteredOverriddenDeclarations
535        ) {
536            for (Set<CallableMemberDescriptor> otherSet : allDeclarationSets) {
537                if (otherSet == declarationSet) continue;
538                if (otherSet.containsAll(declarationSet)) return false;
539                if (Collections.disjoint(allFilteredOverriddenDeclarations, declarationSet)) return false;
540            }
541            return true;
542        }
543    
544        @NotNull
545        private static Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> collectOverriddenDeclarations(
546                @NotNull Collection<? extends CallableMemberDescriptor> directOverriddenDescriptors
547        ) {
548            Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenDeclarationsByDirectParent = Maps.newLinkedHashMap();
549            for (CallableMemberDescriptor descriptor : directOverriddenDescriptors) {
550                Set<CallableMemberDescriptor> overriddenDeclarations = getOverriddenDeclarations(descriptor);
551                Set<CallableMemberDescriptor> filteredOverrides = filterOutOverridden(overriddenDeclarations);
552                overriddenDeclarationsByDirectParent.put(descriptor, new LinkedHashSet<CallableMemberDescriptor>(filteredOverrides));
553            }
554            return overriddenDeclarationsByDirectParent;
555        }
556    
557        /**
558         * @return overridden real descriptors (not fake overrides). Note that all usages of this method should be followed by calling
559         * {@link #filterOutOverridden(java.util.Set)} or {@link #filterOutOverriding(java.util.Set)}, because some of the declarations
560         * can override the other
561         * TODO: merge this method with filterOutOverridden
562         */
563        @NotNull
564        public static Set<CallableMemberDescriptor> getOverriddenDeclarations(@NotNull CallableMemberDescriptor descriptor) {
565            Set<CallableMemberDescriptor> result = new LinkedHashSet<CallableMemberDescriptor>();
566            getOverriddenDeclarations(descriptor, result);
567            return result;
568        }
569    
570        private static void getOverriddenDeclarations(
571                @NotNull CallableMemberDescriptor descriptor,
572                @NotNull Set<CallableMemberDescriptor> result
573        ) {
574            if (descriptor.getKind().isReal()) {
575                result.add(descriptor);
576            }
577            else {
578                if (descriptor.getOverriddenDescriptors().isEmpty()) {
579                    throw new IllegalStateException("No overridden descriptors found for (fake override) " + descriptor);
580                }
581                for (CallableMemberDescriptor overridden : descriptor.getOverriddenDescriptors()) {
582                    getOverriddenDeclarations(overridden, result);
583                }
584            }
585        }
586    
587        private interface CheckOverrideReportStrategy {
588            void overridingFinalMember(@NotNull CallableMemberDescriptor overridden);
589    
590            void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden);
591    
592            void propertyTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden);
593    
594            void varOverriddenByVal(@NotNull CallableMemberDescriptor overridden);
595    
596            void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor invisibleOverridden);
597    
598            void nothingToOverride();
599        }
600    
601        private void checkOverrideForMember(@NotNull final CallableMemberDescriptor declared) {
602            if (declared.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED) {
603                // TODO: this should be replaced soon by a framework of synthesized member generation tools
604                if (declared.getName().asString().startsWith(DescriptorResolver.COMPONENT_FUNCTION_NAME_PREFIX)) {
605                    checkOverrideForComponentFunction(declared);
606                }
607                return;
608            }
609    
610            if (declared.getKind() != CallableMemberDescriptor.Kind.DECLARATION) {
611                return;
612            }
613    
614            final JetNamedDeclaration member = (JetNamedDeclaration) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), declared);
615            if (member == null) {
616                throw new IllegalStateException("declared descriptor is not resolved to declaration: " + declared);
617            }
618    
619            JetModifierList modifierList = member.getModifierList();
620            boolean hasOverrideNode = modifierList != null && modifierList.hasModifier(JetTokens.OVERRIDE_KEYWORD);
621            Set<? extends CallableMemberDescriptor> overriddenDescriptors = declared.getOverriddenDescriptors();
622    
623            if (hasOverrideNode) {
624                checkOverridesForMemberMarkedOverride(declared, true, new CheckOverrideReportStrategy() {
625                    private boolean finalOverriddenError = false;
626                    private boolean typeMismatchError = false;
627                    private boolean kindMismatchError = false;
628    
629                    @Override
630                    public void overridingFinalMember(@NotNull CallableMemberDescriptor overridden) {
631                        if (!finalOverriddenError) {
632                            finalOverriddenError = true;
633                            trace.report(OVERRIDING_FINAL_MEMBER.on(member, overridden, overridden.getContainingDeclaration()));
634                        }
635                    }
636    
637                    @Override
638                    public void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden) {
639                        if (!typeMismatchError) {
640                            typeMismatchError = true;
641                            trace.report(RETURN_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden));
642                        }
643                    }
644    
645                    @Override
646                    public void propertyTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden) {
647                        if (!typeMismatchError) {
648                            typeMismatchError = true;
649                            trace.report(PROPERTY_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden));
650                        }
651                    }
652    
653                    @Override
654                    public void varOverriddenByVal(@NotNull CallableMemberDescriptor overridden) {
655                        if (!kindMismatchError) {
656                            kindMismatchError = true;
657                            trace.report(VAR_OVERRIDDEN_BY_VAL.on((JetProperty) member, (PropertyDescriptor) declared, (PropertyDescriptor) overridden));
658                        }
659                    }
660    
661                    @Override
662                    public void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor invisibleOverridden) {
663                        trace.report(CANNOT_OVERRIDE_INVISIBLE_MEMBER.on(member, declared, invisibleOverridden));
664                    }
665    
666                    @Override
667                    public void nothingToOverride() {
668                        trace.report(NOTHING_TO_OVERRIDE.on(member, declared));
669                    }
670                });
671            }
672            else if (!overriddenDescriptors.isEmpty()) {
673                CallableMemberDescriptor overridden = overriddenDescriptors.iterator().next();
674                trace.report(VIRTUAL_MEMBER_HIDDEN.on(member, declared, overridden, overridden.getContainingDeclaration()));
675            }
676        }
677    
678        private static void checkOverridesForMemberMarkedOverride(
679                @NotNull CallableMemberDescriptor declared,
680                boolean checkIfOverridesNothing,
681                @NotNull CheckOverrideReportStrategy reportError
682        ) {
683            Set<? extends CallableMemberDescriptor> overriddenDescriptors = declared.getOverriddenDescriptors();
684    
685            for (CallableMemberDescriptor overridden : overriddenDescriptors) {
686                if (overridden == null) continue;
687    
688                if (!overridden.getModality().isOverridable()) {
689                    reportError.overridingFinalMember(overridden);
690                }
691    
692                if (declared instanceof PropertyDescriptor &&
693                    !isPropertyTypeOkForOverride((PropertyDescriptor) overridden, (PropertyDescriptor) declared)) {
694                    reportError.propertyTypeMismatchOnOverride(overridden);
695                }
696                else if (!isReturnTypeOkForOverride(overridden, declared)) {
697                    reportError.returnTypeMismatchOnOverride(overridden);
698                }
699    
700                if (checkPropertyKind(overridden, true) && checkPropertyKind(declared, false)) {
701                    reportError.varOverriddenByVal(overridden);
702                }
703            }
704    
705            if (checkIfOverridesNothing && overriddenDescriptors.isEmpty()) {
706                DeclarationDescriptor containingDeclaration = declared.getContainingDeclaration();
707                assert containingDeclaration instanceof ClassDescriptor : "Overrides may only be resolved in a class, but " + declared + " comes from " + containingDeclaration;
708                ClassDescriptor declaringClass = (ClassDescriptor) containingDeclaration;
709    
710                CallableMemberDescriptor invisibleOverriddenDescriptor = findInvisibleOverriddenDescriptor(declared, declaringClass);
711                if (invisibleOverriddenDescriptor != null) {
712                    reportError.cannotOverrideInvisibleMember(invisibleOverriddenDescriptor);
713                }
714                else {
715                    reportError.nothingToOverride();
716                }
717            }
718        }
719    
720        public static boolean isReturnTypeOkForOverride(
721                @NotNull CallableDescriptor superDescriptor,
722                @NotNull CallableDescriptor subDescriptor
723        ) {
724            TypeSubstitutor typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor);
725            if (typeSubstitutor == null) return false;
726    
727            JetType superReturnType = superDescriptor.getReturnType();
728            assert superReturnType != null;
729    
730            JetType subReturnType = subDescriptor.getReturnType();
731            assert subReturnType != null;
732    
733            JetType substitutedSuperReturnType = typeSubstitutor.substitute(superReturnType, Variance.OUT_VARIANCE);
734            assert substitutedSuperReturnType != null;
735    
736            return JetTypeChecker.DEFAULT.isSubtypeOf(subReturnType, substitutedSuperReturnType);
737        }
738    
739        @Nullable
740        private static TypeSubstitutor prepareTypeSubstitutor(
741                @NotNull CallableDescriptor superDescriptor,
742                @NotNull CallableDescriptor subDescriptor
743        ) {
744            List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
745            List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();
746            if (subTypeParameters.size() != superTypeParameters.size()) return null;
747    
748            Map<TypeConstructor, TypeProjection> substitutionContext = Maps.newHashMapWithExpectedSize(superTypeParameters.size());
749            for (int i = 0; i < superTypeParameters.size(); i++) {
750                TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i);
751                TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i);
752                substitutionContext.put(
753                        superTypeParameter.getTypeConstructor(),
754                        new TypeProjectionImpl(subTypeParameter.getDefaultType())
755                );
756            }
757            return TypeSubstitutor.create(substitutionContext);
758        }
759    
760        public static boolean isPropertyTypeOkForOverride(
761                @NotNull PropertyDescriptor superDescriptor,
762                @NotNull PropertyDescriptor subDescriptor
763        ) {
764            TypeSubstitutor typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor);
765            if (typeSubstitutor == null) return false;
766    
767            if (!superDescriptor.isVar()) return true;
768    
769            JetType substitutedSuperReturnType = typeSubstitutor.substitute(superDescriptor.getType(), Variance.OUT_VARIANCE);
770            assert substitutedSuperReturnType != null;
771            return JetTypeChecker.DEFAULT.equalTypes(subDescriptor.getType(), substitutedSuperReturnType);
772        }
773    
774        private void checkOverrideForComponentFunction(@NotNull final CallableMemberDescriptor componentFunction) {
775            final JetAnnotationEntry dataAnnotation = findDataAnnotationForDataClass(componentFunction.getContainingDeclaration());
776    
777            checkOverridesForMemberMarkedOverride(componentFunction, false, new CheckOverrideReportStrategy() {
778                private boolean overrideConflict = false;
779    
780                @Override
781                public void overridingFinalMember(@NotNull CallableMemberDescriptor overridden) {
782                    if (!overrideConflict) {
783                        overrideConflict = true;
784                        trace.report(DATA_CLASS_OVERRIDE_CONFLICT.on(dataAnnotation, componentFunction, overridden.getContainingDeclaration()));
785                    }
786                }
787    
788                @Override
789                public void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden) {
790                    if (!overrideConflict) {
791                        overrideConflict = true;
792                        trace.report(DATA_CLASS_OVERRIDE_CONFLICT.on(dataAnnotation, componentFunction, overridden.getContainingDeclaration()));
793                    }
794                }
795    
796                @Override
797                public void propertyTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden) {
798                    throw new IllegalStateException("Component functions are not properties");
799                }
800    
801                @Override
802                public void varOverriddenByVal(@NotNull CallableMemberDescriptor overridden) {
803                    throw new IllegalStateException("Component functions are not properties");
804                }
805    
806                @Override
807                public void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor invisibleOverridden) {
808                    throw new IllegalStateException("CANNOT_OVERRIDE_INVISIBLE_MEMBER should be reported on the corresponding property");
809                }
810    
811                @Override
812                public void nothingToOverride() {
813                    throw new IllegalStateException("Component functions are OK to override nothing");
814                }
815            });
816        }
817    
818        @NotNull
819        private JetAnnotationEntry findDataAnnotationForDataClass(@NotNull DeclarationDescriptor dataClass) {
820            ClassDescriptor stdDataClassAnnotation = KotlinBuiltIns.getInstance().getDataClassAnnotation();
821            AnnotationDescriptor annotation = dataClass.getAnnotations().findAnnotation(DescriptorUtils.getFqNameSafe(stdDataClassAnnotation));
822            if (annotation == null) {
823                throw new IllegalStateException("No data annotation is found for data class " + dataClass);
824            }
825            return BindingContextUtils.getNotNull(trace.getBindingContext(),
826                                                  BindingContext.ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT,
827                                                  annotation);
828        }
829    
830        @Nullable
831        private static CallableMemberDescriptor findInvisibleOverriddenDescriptor(
832                @NotNull CallableMemberDescriptor declared,
833                @NotNull ClassDescriptor declaringClass
834        ) {
835            for (JetType supertype : declaringClass.getTypeConstructor().getSupertypes()) {
836                Set<CallableMemberDescriptor> all = Sets.newLinkedHashSet();
837                all.addAll(supertype.getMemberScope().getFunctions(declared.getName()));
838                //noinspection unchecked
839                all.addAll((Collection) supertype.getMemberScope().getProperties(declared.getName()));
840                for (CallableMemberDescriptor fromSuper : all) {
841                    if (OverridingUtil.DEFAULT.isOverridableBy(fromSuper, declared).getResult() == OVERRIDABLE) {
842                        if (Visibilities.isVisible(fromSuper, declared)) {
843                            throw new IllegalStateException("Descriptor " + fromSuper + " is overridable by " + declared +
844                                                            " and visible but does not appear in its getOverriddenDescriptors()");
845                        }
846                        return fromSuper;
847                    }
848                }
849            }
850            return null;
851        }
852    
853        private void checkParameterOverridesForAllClasses(@NotNull TopDownAnalysisContext c) {
854            for (ClassDescriptorWithResolutionScopes classDescriptor : c.getDeclaredClasses().values()) {
855                for (DeclarationDescriptor member : classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
856                    if (member instanceof CallableMemberDescriptor) {
857                        checkOverridesForParameters((CallableMemberDescriptor) member);
858                    }
859                }
860            }
861        }
862    
863        private void checkOverridesForParameters(@NotNull CallableMemberDescriptor declared) {
864            boolean isDeclaration = declared.getKind() == CallableMemberDescriptor.Kind.DECLARATION;
865            if (isDeclaration) {
866                // No check if the function is not marked as 'override'
867                JetModifierListOwner declaration =
868                        (JetModifierListOwner) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), declared);
869                if (declaration != null && !declaration.hasModifier(JetTokens.OVERRIDE_KEYWORD)) {
870                    return;
871                }
872            }
873    
874            // Let p1 be a parameter of the overriding function
875            // Let p2 be a parameter of the function being overridden
876            // Then
877            //  a) p1 is not allowed to have a default value declared
878            //  b) p1 must have the same name as p2
879            for (ValueParameterDescriptor parameterFromSubclass : declared.getValueParameters()) {
880                int defaultsInSuper = 0;
881                for (ValueParameterDescriptor parameterFromSuperclass : parameterFromSubclass.getOverriddenDescriptors()) {
882                    if (parameterFromSuperclass.declaresDefaultValue()) {
883                        defaultsInSuper++;
884                    }
885                }
886                boolean multipleDefaultsInSuper = defaultsInSuper > 1;
887    
888                if (isDeclaration) {
889                    checkNameAndDefaultForDeclaredParameter(parameterFromSubclass, multipleDefaultsInSuper);
890                }
891                else {
892                    checkNameAndDefaultForFakeOverrideParameter(declared, parameterFromSubclass, multipleDefaultsInSuper);
893                }
894            }
895        }
896    
897        private void checkNameAndDefaultForDeclaredParameter(@NotNull ValueParameterDescriptor descriptor, boolean multipleDefaultsInSuper) {
898            JetParameter parameter = (JetParameter) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), descriptor);
899            assert parameter != null : "Declaration not found for parameter: " + descriptor;
900    
901            if (descriptor.declaresDefaultValue()) {
902                trace.report(DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE.on(parameter));
903            }
904    
905            if (multipleDefaultsInSuper) {
906                trace.report(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES.on(parameter, descriptor));
907            }
908    
909            for (ValueParameterDescriptor parameterFromSuperclass : descriptor.getOverriddenDescriptors()) {
910                if (shouldReportParameterNameOverrideWarning(descriptor, parameterFromSuperclass)) {
911                    //noinspection ConstantConditions
912                    trace.report(PARAMETER_NAME_CHANGED_ON_OVERRIDE.on(
913                            parameter,
914                            (ClassDescriptor) parameterFromSuperclass.getContainingDeclaration().getContainingDeclaration(),
915                            parameterFromSuperclass)
916                    );
917                }
918            }
919        }
920    
921        private void checkNameAndDefaultForFakeOverrideParameter(
922                @NotNull CallableMemberDescriptor containingFunction,
923                @NotNull ValueParameterDescriptor descriptor,
924                boolean multipleDefaultsInSuper
925        ) {
926            DeclarationDescriptor containingClass = containingFunction.getContainingDeclaration();
927            JetClassOrObject classElement =
928                    (JetClassOrObject) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), containingClass);
929            assert classElement != null : "Declaration not found for class: " + containingClass;
930    
931            if (multipleDefaultsInSuper) {
932                trace.report(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE.on(classElement, descriptor));
933            }
934    
935            for (ValueParameterDescriptor parameterFromSuperclass : descriptor.getOverriddenDescriptors()) {
936                if (shouldReportParameterNameOverrideWarning(descriptor, parameterFromSuperclass)) {
937                    trace.report(DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES.on(
938                            classElement,
939                            containingFunction.getOverriddenDescriptors(),
940                            parameterFromSuperclass.getIndex() + 1)
941                    );
942                }
943            }
944        }
945    
946        private static boolean shouldReportParameterNameOverrideWarning(
947                @NotNull ValueParameterDescriptor parameterFromSubclass,
948                @NotNull ValueParameterDescriptor parameterFromSuperclass
949        ) {
950            DeclarationDescriptor subFunction = parameterFromSubclass.getContainingDeclaration();
951            DeclarationDescriptor superFunction = parameterFromSuperclass.getContainingDeclaration();
952            return subFunction instanceof CallableDescriptor && ((CallableDescriptor) subFunction).hasStableParameterNames() &&
953                   superFunction instanceof CallableDescriptor && ((CallableDescriptor) superFunction).hasStableParameterNames() &&
954                   !parameterFromSuperclass.getName().equals(parameterFromSubclass.getName());
955        }
956    
957        private static boolean checkPropertyKind(@NotNull CallableMemberDescriptor descriptor, boolean isVar) {
958            return descriptor instanceof PropertyDescriptor && ((PropertyDescriptor) descriptor).isVar() == isVar;
959        }
960    
961        private void checkVisibility(@NotNull TopDownAnalysisContext c) {
962            for (Map.Entry<JetDeclaration, CallableMemberDescriptor> entry : c.getMembers().entrySet()) {
963                checkVisibilityForMember(entry.getKey(), entry.getValue());
964            }
965        }
966    
967        private void checkVisibilityForMember(@NotNull JetDeclaration declaration, @NotNull CallableMemberDescriptor memberDescriptor) {
968            Visibility visibility = memberDescriptor.getVisibility();
969            for (CallableMemberDescriptor descriptor : memberDescriptor.getOverriddenDescriptors()) {
970                Integer compare = Visibilities.compare(visibility, descriptor.getVisibility());
971                if (compare == null) {
972                    trace.report(CANNOT_CHANGE_ACCESS_PRIVILEGE.on(declaration, descriptor.getVisibility(), descriptor, descriptor.getContainingDeclaration()));
973                    return;
974                }
975                else if (compare < 0) {
976                    trace.report(CANNOT_WEAKEN_ACCESS_PRIVILEGE.on(declaration, descriptor.getVisibility(), descriptor, descriptor.getContainingDeclaration()));
977                    return;
978                }
979            }
980        }
981    
982        @NotNull
983        public static <D extends CallableMemberDescriptor> Set<D> getDirectlyOverriddenDeclarations(@NotNull D descriptor) {
984            Set<D> result = Sets.newHashSet();
985            //noinspection unchecked
986            Set<D> overriddenDescriptors = (Set<D>) descriptor.getOverriddenDescriptors();
987            for (D overriddenDescriptor : overriddenDescriptors) {
988                CallableMemberDescriptor.Kind kind = overriddenDescriptor.getKind();
989                if (kind == DECLARATION) {
990                    result.add(overriddenDescriptor);
991                }
992                else if (kind == FAKE_OVERRIDE || kind == DELEGATION) {
993                    result.addAll(getDirectlyOverriddenDeclarations(overriddenDescriptor));
994                }
995                else if (kind == SYNTHESIZED) {
996                    //do nothing
997                }
998                else {
999                    throw new AssertionError("Unexpected callable kind " + kind);
1000                }
1001            }
1002            return filterOutOverridden(result);
1003        }
1004    
1005        @NotNull
1006        public static <D extends CallableMemberDescriptor> Set<D> getAllOverriddenDeclarations(@NotNull D memberDescriptor) {
1007            Set<D> result = Sets.newHashSet();
1008            for (CallableMemberDescriptor overriddenDeclaration : memberDescriptor.getOverriddenDescriptors()) {
1009                CallableMemberDescriptor.Kind kind = overriddenDeclaration.getKind();
1010                if (kind == DECLARATION) {
1011                    //noinspection unchecked
1012                    result.add((D) overriddenDeclaration);
1013                }
1014                else if (kind == DELEGATION || kind == FAKE_OVERRIDE || kind == SYNTHESIZED) {
1015                    //do nothing
1016                }
1017                else {
1018                    throw new AssertionError("Unexpected callable kind " + kind);
1019                }
1020                //noinspection unchecked
1021                result.addAll(getAllOverriddenDeclarations((D) overriddenDeclaration));
1022            }
1023            return result;
1024        }
1025    
1026        @NotNull
1027        @ReadOnly
1028        public static <D extends CallableMemberDescriptor> Set<D> getDeepestSuperDeclarations(@NotNull D functionDescriptor) {
1029            Set<D> overriddenDeclarations = getAllOverriddenDeclarations(functionDescriptor);
1030            if (overriddenDeclarations.isEmpty()) {
1031                return Collections.singleton(functionDescriptor);
1032            }
1033    
1034            return filterOutOverriding(overriddenDeclarations);
1035        }
1036    }