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