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