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.dataClassUtils.DataClassUtilsPackage;
039    import org.jetbrains.jet.lang.resolve.name.Name;
040    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
041    import org.jetbrains.jet.lang.types.*;
042    import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
043    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
044    import org.jetbrains.jet.lexer.JetTokens;
045    import org.jetbrains.jet.utils.HashSetUtil;
046    
047    import javax.inject.Inject;
048    import java.util.*;
049    
050    import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.*;
051    import static org.jetbrains.jet.lang.diagnostics.Errors.*;
052    import static org.jetbrains.jet.lang.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE;
053    
054    public class OverrideResolver {
055    
056        private BindingTrace trace;
057    
058        @Inject
059        public void setTrace(BindingTrace trace) {
060            this.trace = trace;
061        }
062    
063    
064    
065        public void process(@NotNull TopDownAnalysisContext c) {
066            //all created fake descriptors are stored to resolve visibility on them later
067            generateOverridesAndDelegation(c);
068    
069            check(c);
070        }
071    
072        public void check(@NotNull TopDownAnalysisContext c) {
073            checkVisibility(c);
074            checkOverrides(c);
075            checkParameterOverridesForAllClasses(c);
076        }
077    
078        /**
079         * Generate fake overrides and add overridden descriptors to existing descriptors.
080         */
081        private void generateOverridesAndDelegation(@NotNull TopDownAnalysisContext c) {
082            Set<ClassDescriptorWithResolutionScopes> ourClasses = new HashSet<ClassDescriptorWithResolutionScopes>(c.getAllClasses());
083            Set<ClassifierDescriptor> processed = new HashSet<ClassifierDescriptor>();
084    
085            for (MutableClassDescriptor klass : ContainerUtil.reverse(c.getClassesTopologicalOrder())) {
086                if (ourClasses.contains(klass)) {
087                    generateOverridesAndDelegationInAClass(klass, processed, ourClasses);
088    
089                    MutableClassDescriptor classObject = klass.getClassObjectDescriptor();
090                    if (classObject != null) {
091                        generateOverridesAndDelegationInAClass(classObject, processed, ourClasses);
092                    }
093                }
094            }
095        }
096    
097        private void generateOverridesAndDelegationInAClass(
098                @NotNull MutableClassDescriptor classDescriptor,
099                @NotNull Set<ClassifierDescriptor> processed,
100                @NotNull Set<ClassDescriptorWithResolutionScopes> classesBeingAnalyzed
101                // to filter out classes such as stdlib and others that come from dependencies
102        ) {
103            if (!processed.add(classDescriptor)) {
104                return;
105            }
106    
107            for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
108                ClassDescriptor superclass = (ClassDescriptor) supertype.getConstructor().getDeclarationDescriptor();
109                if (superclass instanceof MutableClassDescriptor && classesBeingAnalyzed.contains(superclass)) {
110                    generateOverridesAndDelegationInAClass((MutableClassDescriptor) superclass, processed, classesBeingAnalyzed);
111                }
112            }
113    
114            JetClassOrObject classOrObject = (JetClassOrObject) DescriptorToSourceUtils.classDescriptorToDeclaration(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 = (JetDeclaration) DescriptorToSourceUtils.descriptorToDeclaration(fromCurrent);
159                                //noinspection ConstantConditions
160                                trace.report(CONFLICTING_OVERLOADS.on(declaration, fromCurrent, fromCurrent.getContainingDeclaration().getName().asString()));
161                            }
162                        });
163            }
164            resolveUnknownVisibilities(classDescriptor.getAllCallableMembers(), trace);
165        }
166    
167        public static void resolveUnknownVisibilities(
168                @NotNull Collection<? extends CallableMemberDescriptor> descriptors,
169                @NotNull BindingTrace trace
170        ) {
171            for (CallableMemberDescriptor descriptor : descriptors) {
172                OverridingUtil.resolveUnknownVisibilityForMember(descriptor, createCannotInferVisibilityReporter(trace));
173            }
174        }
175    
176        @NotNull
177        public static Function1<CallableMemberDescriptor, Unit> createCannotInferVisibilityReporter(@NotNull final BindingTrace trace) {
178            return new Function1<CallableMemberDescriptor, Unit>() {
179                @Override
180                public Unit invoke(@NotNull CallableMemberDescriptor descriptor) {
181                    DeclarationDescriptor reportOn;
182                    if (descriptor.getKind() == FAKE_OVERRIDE || descriptor.getKind() == DELEGATION) {
183                        reportOn = DescriptorUtils.getParentOfType(descriptor, ClassDescriptor.class);
184                    }
185                    else if (descriptor instanceof PropertyAccessorDescriptor && ((PropertyAccessorDescriptor) descriptor).isDefault()) {
186                        reportOn = ((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty();
187                    }
188                    else {
189                        reportOn = descriptor;
190                    }
191                    //noinspection ConstantConditions
192                    PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(reportOn);
193                    if (element instanceof JetDeclaration) {
194                        trace.report(CANNOT_INFER_VISIBILITY.on((JetDeclaration) element, descriptor));
195                    }
196                    return Unit.INSTANCE$;
197                }
198            };
199        }
200    
201        private static enum Filtering {
202            RETAIN_OVERRIDING,
203            RETAIN_OVERRIDDEN
204        }
205    
206        @NotNull
207        public static <D extends CallableDescriptor> Set<D> filterOutOverridden(@NotNull Set<D> candidateSet) {
208            //noinspection unchecked
209            return filterOverrides(candidateSet, Function.ID, Filtering.RETAIN_OVERRIDING);
210        }
211    
212        @NotNull
213        public static <D> Set<D> filterOutOverriding(@NotNull Set<D> candidateSet) {
214            //noinspection unchecked
215            return filterOverrides(candidateSet, Function.ID, Filtering.RETAIN_OVERRIDDEN);
216        }
217    
218        @NotNull
219        public static <D> Set<D> filterOutOverridden(
220                @NotNull Set<D> candidateSet,
221                @NotNull Function<? super D, ? extends CallableDescriptor> transform
222        ) {
223            return filterOverrides(candidateSet, transform, Filtering.RETAIN_OVERRIDING);
224        }
225    
226        @NotNull
227        private static <D> Set<D> filterOverrides(
228                @NotNull Set<D> candidateSet,
229                @NotNull final Function<? super D, ? extends CallableDescriptor> transform,
230                @NotNull Filtering filtering
231        ) {
232            if (candidateSet.size() <= 1) return candidateSet;
233    
234            // In a multi-module project different "copies" of the same class may be present in different libraries,
235            // that's why we use structural equivalence for members (DescriptorEquivalenceForOverrides).
236            // Here we filter out structurally equivalent descriptors before processing overrides, because such descriptors
237            // "override" each other (overrides(f, g) = overrides(g, f) = true) and the code below removes them all from the
238            // candidates, unless we first compute noDuplicates
239            Set<D> noDuplicates = HashSetUtil.linkedHashSet(
240                    candidateSet,
241                    new EqualityPolicy<D>() {
242                        @Override
243                        public int getHashCode(D d) {
244                            return DescriptorUtils.getFqName(transform.fun(d).getContainingDeclaration()).hashCode();
245                        }
246    
247                        @Override
248                        public boolean isEqual(D d1, D d2) {
249                            CallableDescriptor f = transform.fun(d1);
250                            CallableDescriptor g = transform.fun(d2);
251                            return DescriptorEquivalenceForOverrides.INSTANCE$.areEquivalent(f.getOriginal(), g.getOriginal());
252                        }
253                    });
254    
255            Set<D> candidates = Sets.newLinkedHashSet();
256            outerLoop:
257            for (D meD : noDuplicates) {
258                CallableDescriptor me = transform.fun(meD);
259                for (D otherD : noDuplicates) {
260                    CallableDescriptor other = transform.fun(otherD);
261                    if (me == other) continue;
262                    if (filtering == Filtering.RETAIN_OVERRIDING) {
263                        if (overrides(other, me)) {
264                            continue outerLoop;
265                        }
266                    }
267                    else if (filtering == Filtering.RETAIN_OVERRIDDEN) {
268                        if (overrides(me, other)) {
269                            continue outerLoop;
270                        }
271                    }
272                    else {
273                        throw new AssertionError("Unexpected Filtering object: " + filtering);
274                    }
275                }
276                for (D otherD : candidates) {
277                    CallableDescriptor other = transform.fun(otherD);
278                    if (me.getOriginal() == other.getOriginal()
279                        && OverridingUtil.DEFAULT.isOverridableBy(other, me).getResult() == OVERRIDABLE
280                        && OverridingUtil.DEFAULT.isOverridableBy(me, other).getResult() == OVERRIDABLE) {
281                        continue outerLoop;
282                    }
283                }
284                candidates.add(meD);
285            }
286    
287            assert !candidates.isEmpty() : "All candidates filtered out from " + candidateSet;
288    
289            return candidates;
290        }
291    
292        // check whether f overrides g
293        public static <D extends CallableDescriptor> boolean overrides(@NotNull D f, @NotNull D g) {
294            // This first check cover the case of duplicate classes in different modules:
295            // when B is defined in modules m1 and m2, and C (indirectly) inherits from both versions,
296            // we'll be getting sets of members that do not override each other, but are structurally equivalent.
297            // As other code relies on no equal descriptors passed here, we guard against f == g, but this may not be necessary
298            if (!f.equals(g) && DescriptorEquivalenceForOverrides.INSTANCE$.areEquivalent(f.getOriginal(), g.getOriginal())) return true;
299            CallableDescriptor originalG = g.getOriginal();
300            for (D overriddenFunction : getAllOverriddenDescriptors(f)) {
301                if (DescriptorEquivalenceForOverrides.INSTANCE$.areEquivalent(originalG, overriddenFunction.getOriginal())) return true;
302            }
303            return false;
304        }
305    
306        @NotNull
307        @SuppressWarnings("unchecked")
308        public static <D extends CallableDescriptor> Set<D> getAllOverriddenDescriptors(@NotNull D f) {
309            Set<D> result = new LinkedHashSet<D>();
310            collectAllOverriddenDescriptors((D) f.getOriginal(), result);
311            return result;
312        }
313    
314        private static <D extends CallableDescriptor> void collectAllOverriddenDescriptors(@NotNull D current, @NotNull Set<D> result) {
315            if (result.contains(current)) return;
316            for (CallableDescriptor callableDescriptor : current.getOriginal().getOverriddenDescriptors()) {
317                @SuppressWarnings("unchecked")
318                D descriptor = (D) callableDescriptor;
319                collectAllOverriddenDescriptors(descriptor, result);
320                result.add(descriptor);
321            }
322        }
323    
324        private static <T extends DeclarationDescriptor> MultiMap<Name, T> groupDescriptorsByName(Collection<T> properties) {
325            MultiMap<Name, T> r = new LinkedMultiMap<Name, T>();
326            for (T property : properties) {
327                r.putValue(property.getName(), property);
328            }
329            return r;
330        }
331    
332    
333        private static List<CallableMemberDescriptor> getCallableMembersFromSupertypes(ClassDescriptor classDescriptor) {
334            Set<CallableMemberDescriptor> r = Sets.newLinkedHashSet();
335            for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
336                r.addAll(getCallableMembersFromType(supertype.getMemberScope()));
337            }
338            return new ArrayList<CallableMemberDescriptor>(r);
339        }
340    
341        private static List<CallableMemberDescriptor> getCallableMembersFromType(JetScope scope) {
342            List<CallableMemberDescriptor> r = Lists.newArrayList();
343            for (DeclarationDescriptor decl : scope.getAllDescriptors()) {
344                if (decl instanceof PropertyDescriptor || decl instanceof SimpleFunctionDescriptor) {
345                    r.add((CallableMemberDescriptor) decl);
346                }
347            }
348            return r;
349        }
350    
351        private void checkOverrides(@NotNull TopDownAnalysisContext c) {
352            for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
353                checkOverridesInAClass(c, entry.getValue(), entry.getKey());
354            }
355        }
356    
357        private void checkOverridesInAClass(@NotNull TopDownAnalysisContext c, @NotNull ClassDescriptorWithResolutionScopes classDescriptor, @NotNull JetClassOrObject klass) {
358            if (c.getTopDownAnalysisParameters().isAnalyzingBootstrapLibrary()) return;
359    
360            // Check overrides for internal consistency
361            for (CallableMemberDescriptor member : classDescriptor.getDeclaredCallableMembers()) {
362                checkOverrideForMember(member);
363            }
364    
365            // Check if everything that must be overridden, actually is
366            // More than one implementation or no implementations at all
367            Set<CallableMemberDescriptor> abstractNoImpl = Sets.newLinkedHashSet();
368            Set<CallableMemberDescriptor> manyImpl = Sets.newLinkedHashSet();
369            collectMissingImplementations(classDescriptor, abstractNoImpl, manyImpl);
370    
371            if (!manyImpl.isEmpty()) {
372                trace.report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(klass, klass, manyImpl.iterator().next()));
373            }
374    
375            if (classDescriptor.getModality() != Modality.ABSTRACT && !abstractNoImpl.isEmpty()) {
376                trace.report(ABSTRACT_MEMBER_NOT_IMPLEMENTED.on(klass, klass, abstractNoImpl.iterator().next()));
377            }
378        }
379    
380        @NotNull
381        public static Set<CallableMemberDescriptor> getMissingImplementations(@NotNull ClassDescriptor classDescriptor) {
382            Set<CallableMemberDescriptor> result = new LinkedHashSet<CallableMemberDescriptor>();
383            collectMissingImplementations(classDescriptor, result, result);
384            return result;
385        }
386    
387        private static void collectMissingImplementations(
388                @NotNull ClassDescriptor classDescriptor,
389                @NotNull Set<CallableMemberDescriptor> abstractNoImpl,
390                @NotNull Set<CallableMemberDescriptor> manyImpl
391        ) {
392            for (DeclarationDescriptor member : classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
393                if (member instanceof CallableMemberDescriptor) {
394                    collectMissingImplementations((CallableMemberDescriptor) member, abstractNoImpl, manyImpl);
395                }
396            }
397        }
398    
399        private static void collectMissingImplementations(
400                @NotNull CallableMemberDescriptor descriptor,
401                @NotNull Set<CallableMemberDescriptor> abstractNoImpl,
402                @NotNull Set<CallableMemberDescriptor> manyImpl
403        ) {
404            if (descriptor.getKind().isReal()) return;
405            if (descriptor.getVisibility() == Visibilities.INVISIBLE_FAKE) return;
406    
407            Collection<? extends CallableMemberDescriptor> directOverridden = descriptor.getOverriddenDescriptors();
408            if (directOverridden.size() == 0) {
409                throw new IllegalStateException("A 'fake override' must override something");
410            }
411    
412            // collects map from the directly overridden descriptor to the set of declarations:
413            // -- if directly overridden is not fake, the set consists of one element: this directly overridden
414            // -- if it's fake, overridden declarations (non-fake) of this descriptor are collected
415            Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenDeclarationsByDirectParent = collectOverriddenDeclarations(directOverridden);
416    
417            List<CallableMemberDescriptor> allOverriddenDeclarations = ContainerUtil.flatten(overriddenDeclarationsByDirectParent.values());
418            Set<CallableMemberDescriptor> allFilteredOverriddenDeclarations = filterOutOverridden(
419                    Sets.newLinkedHashSet(allOverriddenDeclarations));
420    
421            Set<CallableMemberDescriptor> relevantDirectlyOverridden =
422                    getRelevantDirectlyOverridden(overriddenDeclarationsByDirectParent, allFilteredOverriddenDeclarations);
423    
424            List<CallableMemberDescriptor> implementations = collectImplementations(relevantDirectlyOverridden);
425            if (implementations.size() == 1 && isReturnTypeOkForOverride(descriptor, implementations.get(0))) return;
426    
427            List<CallableMemberDescriptor> abstractOverridden = new ArrayList<CallableMemberDescriptor>(allFilteredOverriddenDeclarations.size());
428            List<CallableMemberDescriptor> concreteOverridden = new ArrayList<CallableMemberDescriptor>(allFilteredOverriddenDeclarations.size());
429            filterNotSynthesizedDescriptorsByModality(allFilteredOverriddenDeclarations, abstractOverridden, concreteOverridden);
430    
431            if (implementations.isEmpty()) {
432                abstractNoImpl.addAll(abstractOverridden);
433            }
434            else if (implementations.size() > 1) {
435                manyImpl.addAll(concreteOverridden);
436            }
437            else {
438                abstractNoImpl.addAll(collectAbstractMethodsWithMoreSpecificReturnType(abstractOverridden, implementations.get(0)));
439            }
440        }
441    
442        @NotNull
443        private static List<CallableMemberDescriptor> collectImplementations(@NotNull Set<CallableMemberDescriptor> relevantDirectlyOverridden) {
444            List<CallableMemberDescriptor> result = new ArrayList<CallableMemberDescriptor>(relevantDirectlyOverridden.size());
445            for (CallableMemberDescriptor overriddenDescriptor : relevantDirectlyOverridden) {
446                if (overriddenDescriptor.getModality() != Modality.ABSTRACT) {
447                    result.add(overriddenDescriptor);
448                }
449            }
450            return result;
451        }
452    
453        private static void filterNotSynthesizedDescriptorsByModality(
454                @NotNull Set<CallableMemberDescriptor> allOverriddenDeclarations,
455                @NotNull List<CallableMemberDescriptor> abstractOverridden,
456                @NotNull List<CallableMemberDescriptor> concreteOverridden
457        ) {
458            for (CallableMemberDescriptor overridden : allOverriddenDeclarations) {
459                if (!CallResolverUtil.isOrOverridesSynthesized(overridden)) {
460                    if (overridden.getModality() == Modality.ABSTRACT) {
461                        abstractOverridden.add(overridden);
462                    }
463                    else {
464                        concreteOverridden.add(overridden);
465                    }
466                }
467            }
468        }
469    
470        @NotNull
471        private static List<CallableMemberDescriptor> collectAbstractMethodsWithMoreSpecificReturnType(
472                @NotNull List<CallableMemberDescriptor> abstractOverridden,
473                @NotNull CallableMemberDescriptor implementation
474        ) {
475            List<CallableMemberDescriptor> result = new ArrayList<CallableMemberDescriptor>(abstractOverridden.size());
476            for (CallableMemberDescriptor abstractMember : abstractOverridden) {
477                if (!isReturnTypeOkForOverride(abstractMember, implementation)) {
478                    result.add(abstractMember);
479                }
480            }
481            assert !result.isEmpty() : "Implementation (" + implementation + ") doesn't have the most specific type, " +
482                                       "but none of the other overridden methods does either: " + abstractOverridden;
483            return result;
484        }
485    
486        @NotNull
487        private static Set<CallableMemberDescriptor> getRelevantDirectlyOverridden(
488                @NotNull Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenByParent,
489                @NotNull Set<CallableMemberDescriptor> allFilteredOverriddenDeclarations
490        ) {
491            /* Let the following class hierarchy is declared:
492    
493            trait A { fun foo() = 1 }
494            trait B : A
495            trait C : A
496            trait D : A { override fun foo() = 2 }
497            trait E : B, C, D {}
498    
499            Traits B and C have fake descriptors for function foo.
500            The map 'overriddenByParent' is:
501            { 'foo in B' (fake) -> { 'foo in A' }, 'foo in C' (fake) -> { 'foo in A' }, 'foo in D' -> { 'foo in D'} }
502            This is a map from directly overridden descriptors (functions 'foo' in B, C, D in this example) to the set of declarations (non-fake),
503            that are overridden by this descriptor.
504    
505            The goal is to leave only relevant directly overridden descriptors to count implementations of our fake function on them.
506            In the example above there is no error (trait E inherits only one implementation of 'foo' (from D), because this implementation is more precise).
507            So only 'foo in D' is relevant.
508    
509            Directly overridden descriptor is not relevant if it doesn't add any more appropriate non-fake declarations of the concerned function.
510            More precisely directly overridden descriptor is not relevant if:
511            - it's declaration set is a subset of declaration set for other directly overridden descriptor
512            ('foo in B' is not relevant because it's declaration set is a subset of 'foo in C' function's declaration set)
513            - each member of it's declaration set is overridden by a member of other declaration set
514            ('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')
515    
516            For the last condition allFilteredOverriddenDeclarations helps (for the example above it's { 'foo in A' } only): each declaration set
517            is compared with allFilteredOverriddenDeclarations, if they have no intersection, this means declaration set has only functions that
518            are overridden by some other function and corresponding directly overridden descriptor is not relevant.
519            */
520    
521            for (Iterator<Map.Entry<CallableMemberDescriptor, Set<CallableMemberDescriptor>>> iterator =
522                         overriddenByParent.entrySet().iterator(); iterator.hasNext(); ) {
523                if (!isRelevant(iterator.next().getValue(), overriddenByParent.values(), allFilteredOverriddenDeclarations)) {
524                    iterator.remove();
525                }
526            }
527            return overriddenByParent.keySet();
528        }
529    
530        private static boolean isRelevant(
531                @NotNull Set<CallableMemberDescriptor> declarationSet,
532                @NotNull Collection<Set<CallableMemberDescriptor>> allDeclarationSets,
533                @NotNull Set<CallableMemberDescriptor> allFilteredOverriddenDeclarations
534        ) {
535            for (Set<CallableMemberDescriptor> otherSet : allDeclarationSets) {
536                if (otherSet == declarationSet) continue;
537                if (otherSet.containsAll(declarationSet)) return false;
538                if (Collections.disjoint(allFilteredOverriddenDeclarations, declarationSet)) return false;
539            }
540            return true;
541        }
542    
543        @NotNull
544        private static Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> collectOverriddenDeclarations(
545                @NotNull Collection<? extends CallableMemberDescriptor> directOverriddenDescriptors
546        ) {
547            Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenDeclarationsByDirectParent = Maps.newLinkedHashMap();
548            for (CallableMemberDescriptor descriptor : directOverriddenDescriptors) {
549                Set<CallableMemberDescriptor> overriddenDeclarations = getOverriddenDeclarations(descriptor);
550                Set<CallableMemberDescriptor> filteredOverrides = filterOutOverridden(overriddenDeclarations);
551                overriddenDeclarationsByDirectParent.put(descriptor, new LinkedHashSet<CallableMemberDescriptor>(filteredOverrides));
552            }
553            return overriddenDeclarationsByDirectParent;
554        }
555    
556        /**
557         * @return overridden real descriptors (not fake overrides). Note that all usages of this method should be followed by calling
558         * {@link #filterOutOverridden(java.util.Set)} or {@link #filterOutOverriding(java.util.Set)}, because some of the declarations
559         * can override the other
560         * TODO: merge this method with filterOutOverridden
561         */
562        @NotNull
563        public static Set<CallableMemberDescriptor> getOverriddenDeclarations(@NotNull CallableMemberDescriptor descriptor) {
564            Set<CallableMemberDescriptor> result = new LinkedHashSet<CallableMemberDescriptor>();
565            getOverriddenDeclarations(descriptor, result);
566            return result;
567        }
568    
569        private static void getOverriddenDeclarations(
570                @NotNull CallableMemberDescriptor descriptor,
571                @NotNull Set<CallableMemberDescriptor> result
572        ) {
573            if (descriptor.getKind().isReal()) {
574                result.add(descriptor);
575            }
576            else {
577                if (descriptor.getOverriddenDescriptors().isEmpty()) {
578                    throw new IllegalStateException("No overridden descriptors found for (fake override) " + descriptor);
579                }
580                for (CallableMemberDescriptor overridden : descriptor.getOverriddenDescriptors()) {
581                    getOverriddenDeclarations(overridden, result);
582                }
583            }
584        }
585    
586        private interface CheckOverrideReportStrategy {
587            void overridingFinalMember(@NotNull CallableMemberDescriptor overridden);
588    
589            void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden);
590    
591            void propertyTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden);
592    
593            void varOverriddenByVal(@NotNull CallableMemberDescriptor overridden);
594    
595            void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor invisibleOverridden);
596    
597            void nothingToOverride();
598        }
599    
600        private void checkOverrideForMember(@NotNull final CallableMemberDescriptor declared) {
601            if (declared.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED) {
602                if (DataClassUtilsPackage.isComponentLike(declared.getName())) {
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    }