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 kotlin.CollectionsKt;
020    import kotlin.Unit;
021    import kotlin.jvm.functions.Function1;
022    import org.jetbrains.annotations.NotNull;
023    import org.jetbrains.annotations.Nullable;
024    import org.jetbrains.kotlin.descriptors.*;
025    import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl;
026    import org.jetbrains.kotlin.descriptors.impl.PropertyAccessorDescriptorImpl;
027    import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl;
028    import org.jetbrains.kotlin.name.Name;
029    import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
030    import org.jetbrains.kotlin.types.KotlinType;
031    import org.jetbrains.kotlin.types.TypeConstructor;
032    import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
033    import org.jetbrains.kotlin.utils.DFS;
034    
035    import java.util.*;
036    
037    import static org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.*;
038    
039    public class OverridingUtil {
040    
041        private static final List<ExternalOverridabilityCondition> EXTERNAL_CONDITIONS =
042                CollectionsKt.toList(ServiceLoader.load(
043                        ExternalOverridabilityCondition.class,
044                        ExternalOverridabilityCondition.class.getClassLoader()
045                ));
046    
047        public static final OverridingUtil DEFAULT = new OverridingUtil(new KotlinTypeChecker.TypeConstructorEquality() {
048            @Override
049            public boolean equals(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
050                return a.equals(b);
051            }
052        });
053    
054        @NotNull
055        public static OverridingUtil createWithEqualityAxioms(@NotNull KotlinTypeChecker.TypeConstructorEquality equalityAxioms) {
056            return new OverridingUtil(equalityAxioms);
057        }
058    
059        private final KotlinTypeChecker.TypeConstructorEquality equalityAxioms;
060    
061        private OverridingUtil(KotlinTypeChecker.TypeConstructorEquality axioms) {
062            equalityAxioms = axioms;
063        }
064    
065        @NotNull
066        public OverrideCompatibilityInfo isOverridableBy(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
067            return isOverridableBy(superDescriptor, subDescriptor, false);
068        }
069    
070        @NotNull
071        public OverrideCompatibilityInfo isOverridableByIncludingReturnType(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
072            return isOverridableBy(superDescriptor, subDescriptor, true);
073        }
074    
075        @NotNull
076        private OverrideCompatibilityInfo isOverridableBy(
077                @NotNull CallableDescriptor superDescriptor,
078                @NotNull CallableDescriptor subDescriptor,
079                boolean checkReturnType
080        ) {
081            if (superDescriptor instanceof FunctionDescriptor) {
082                if (!(subDescriptor instanceof FunctionDescriptor)) return OverrideCompatibilityInfo.memberKindMismatch();
083            }
084            else if (superDescriptor instanceof PropertyDescriptor) {
085                if (!(subDescriptor instanceof PropertyDescriptor)) return OverrideCompatibilityInfo.memberKindMismatch();
086            }
087            else {
088                throw new IllegalArgumentException("This type of CallableDescriptor cannot be checked for overridability: " + superDescriptor);
089            }
090    
091            // TODO: check outside of this method
092            if (!superDescriptor.getName().equals(subDescriptor.getName())) {
093                return OverrideCompatibilityInfo.nameMismatch();
094            }
095    
096            OverrideCompatibilityInfo receiverAndParameterResult = checkReceiverAndParameterCount(superDescriptor, subDescriptor);
097            if (receiverAndParameterResult != null) {
098                return receiverAndParameterResult;
099            }
100    
101            List<KotlinType> superValueParameters = compiledValueParameters(superDescriptor);
102            List<KotlinType> subValueParameters = compiledValueParameters(subDescriptor);
103    
104            List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
105            List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();
106    
107            if (superTypeParameters.size() != subTypeParameters.size()) {
108                for (int i = 0; i < superValueParameters.size(); ++i) {
109                    KotlinType superValueParameterType = getUpperBound(superValueParameters.get(i));
110                    KotlinType subValueParameterType = getUpperBound(subValueParameters.get(i));
111                    // TODO: compare erasure
112                    if (!KotlinTypeChecker.DEFAULT.equalTypes(superValueParameterType, subValueParameterType)) {
113                        return OverrideCompatibilityInfo.typeParameterNumberMismatch();
114                    }
115                }
116                return OverrideCompatibilityInfo.valueParameterTypeMismatch(null, null, OverrideCompatibilityInfo.Result.CONFLICT);
117            }
118    
119            final Map<TypeConstructor, TypeConstructor> matchingTypeConstructors = new HashMap<TypeConstructor, TypeConstructor>();
120            for (int i = 0, typeParametersSize = superTypeParameters.size(); i < typeParametersSize; i++) {
121                TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i);
122                TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i);
123                matchingTypeConstructors.put(superTypeParameter.getTypeConstructor(), subTypeParameter.getTypeConstructor());
124            }
125    
126            KotlinTypeChecker.TypeConstructorEquality localEqualityAxioms = new KotlinTypeChecker.TypeConstructorEquality() {
127                @Override
128                public boolean equals(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
129                    if (equalityAxioms.equals(a, b)) return true;
130                    TypeConstructor img1 = matchingTypeConstructors.get(a);
131                    TypeConstructor img2 = matchingTypeConstructors.get(b);
132                    if (!(img1 != null && img1.equals(b)) &&
133                        !(img2 != null && img2.equals(a))) {
134                        return false;
135                    }
136                    return true;
137                }
138            };
139    
140            for (int i = 0, typeParametersSize = superTypeParameters.size(); i < typeParametersSize; i++) {
141                TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i);
142                TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i);
143    
144                if (!areTypesEquivalent(superTypeParameter.getUpperBoundsAsType(), subTypeParameter.getUpperBoundsAsType(), localEqualityAxioms)) {
145                    return OverrideCompatibilityInfo.boundsMismatch(superTypeParameter, subTypeParameter);
146                }
147            }
148    
149            for (int i = 0, unsubstitutedValueParametersSize = superValueParameters.size(); i < unsubstitutedValueParametersSize; i++) {
150                KotlinType superValueParameter = superValueParameters.get(i);
151                KotlinType subValueParameter = subValueParameters.get(i);
152    
153                if (!areTypesEquivalent(superValueParameter, subValueParameter, localEqualityAxioms)) {
154                    return OverrideCompatibilityInfo.valueParameterTypeMismatch(superValueParameter, subValueParameter, INCOMPATIBLE);
155                }
156            }
157    
158            if (checkReturnType) {
159                KotlinType superReturnType = superDescriptor.getReturnType();
160                KotlinType subReturnType = subDescriptor.getReturnType();
161    
162                if (superReturnType != null && subReturnType != null) {
163                    boolean bothErrors = subReturnType.isError() && superReturnType.isError();
164                    if (!bothErrors && !KotlinTypeChecker.withAxioms(localEqualityAxioms).isSubtypeOf(subReturnType, superReturnType)) {
165                        return OverrideCompatibilityInfo.returnTypeMismatch(superReturnType, subReturnType);
166                    }
167                }
168            }
169    
170    
171            for (ExternalOverridabilityCondition externalCondition : EXTERNAL_CONDITIONS) {
172                if (!externalCondition.isOverridable(superDescriptor, subDescriptor)) {
173                    return OverrideCompatibilityInfo.externalConditionFailed(externalCondition.getClass());
174                }
175            }
176    
177            return OverrideCompatibilityInfo.success();
178        }
179    
180        @Nullable
181        static OverrideCompatibilityInfo checkReceiverAndParameterCount(
182                CallableDescriptor superDescriptor,
183                CallableDescriptor subDescriptor
184        ) {
185            if ((superDescriptor.getExtensionReceiverParameter() == null) != (subDescriptor.getExtensionReceiverParameter() == null)) {
186                return OverrideCompatibilityInfo.receiverPresenceMismatch();
187            }
188    
189            if (superDescriptor.getValueParameters().size() != subDescriptor.getValueParameters().size()) {
190                return OverrideCompatibilityInfo.valueParameterNumberMismatch();
191            }
192    
193            return null;
194        }
195    
196        private static boolean areTypesEquivalent(
197                @NotNull KotlinType typeInSuper,
198                @NotNull KotlinType typeInSub,
199                @NotNull KotlinTypeChecker.TypeConstructorEquality axioms
200        ) {
201            boolean bothErrors = typeInSuper.isError() && typeInSub.isError();
202            if (!bothErrors && !KotlinTypeChecker.withAxioms(axioms).equalTypes(typeInSuper, typeInSub)) {
203                return false;
204            }
205            return true;
206        }
207    
208        static List<KotlinType> compiledValueParameters(CallableDescriptor callableDescriptor) {
209            ReceiverParameterDescriptor receiverParameter = callableDescriptor.getExtensionReceiverParameter();
210            ArrayList<KotlinType> parameters = new ArrayList<KotlinType>();
211            if (receiverParameter != null) {
212                parameters.add(receiverParameter.getType());
213            }
214            for (ValueParameterDescriptor valueParameterDescriptor : callableDescriptor.getValueParameters()) {
215                parameters.add(valueParameterDescriptor.getType());
216            }
217            return parameters;
218        }
219    
220        static KotlinType getUpperBound(KotlinType type) {
221            if (type.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
222                return type;
223            }
224            else if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {
225                return ((TypeParameterDescriptor) type.getConstructor().getDeclarationDescriptor()).getUpperBoundsAsType();
226            }
227            else {
228                throw new IllegalStateException("unknown type constructor: " + type.getConstructor().getClass().getName());
229            }
230        }
231    
232        public static void generateOverridesInFunctionGroup(
233                @SuppressWarnings("UnusedParameters")
234                @NotNull Name name, //DO NOT DELETE THIS PARAMETER: needed to make sure all descriptors have the same name
235                @NotNull Collection<? extends CallableMemberDescriptor> membersFromSupertypes,
236                @NotNull Collection<? extends CallableMemberDescriptor> membersFromCurrent,
237                @NotNull ClassDescriptor current,
238                @NotNull DescriptorSink sink
239        ) {
240            Collection<CallableMemberDescriptor> notOverridden = new LinkedHashSet<CallableMemberDescriptor>(membersFromSupertypes);
241    
242            for (CallableMemberDescriptor fromCurrent : membersFromCurrent) {
243                Collection<CallableMemberDescriptor> bound =
244                        extractAndBindOverridesForMember(fromCurrent, membersFromSupertypes, current, sink);
245                notOverridden.removeAll(bound);
246            }
247    
248            createAndBindFakeOverrides(current, notOverridden, sink);
249        }
250    
251        private static Collection<CallableMemberDescriptor> extractAndBindOverridesForMember(
252                @NotNull CallableMemberDescriptor fromCurrent,
253                @NotNull Collection<? extends CallableMemberDescriptor> descriptorsFromSuper,
254                @NotNull ClassDescriptor current,
255                @NotNull DescriptorSink sink
256        ) {
257            Collection<CallableMemberDescriptor> bound = new ArrayList<CallableMemberDescriptor>(descriptorsFromSuper.size());
258            for (CallableMemberDescriptor fromSupertype : descriptorsFromSuper) {
259                OverrideCompatibilityInfo.Result result = DEFAULT.isOverridableBy(fromSupertype, fromCurrent).getResult();
260    
261                boolean isVisible = Visibilities.isVisible(ReceiverValue.IRRELEVANT_RECEIVER, fromSupertype, current);
262                switch (result) {
263                    case OVERRIDABLE:
264                        if (isVisible) {
265                            fromCurrent.addOverriddenDescriptor(fromSupertype);
266                        }
267                        bound.add(fromSupertype);
268                        break;
269                    case CONFLICT:
270                        if (isVisible) {
271                            sink.conflict(fromSupertype, fromCurrent);
272                        }
273                        bound.add(fromSupertype);
274                        break;
275                    case INCOMPATIBLE:
276                        break;
277                }
278            }
279            return bound;
280        }
281    
282        private static void createAndBindFakeOverrides(
283                @NotNull ClassDescriptor current,
284                @NotNull Collection<CallableMemberDescriptor> notOverridden,
285                @NotNull DescriptorSink sink
286        ) {
287            Queue<CallableMemberDescriptor> fromSuperQueue = new LinkedList<CallableMemberDescriptor>(notOverridden);
288            while (!fromSuperQueue.isEmpty()) {
289                CallableMemberDescriptor notOverriddenFromSuper = VisibilityUtilKt.findMemberWithMaxVisibility(fromSuperQueue);
290                Collection<CallableMemberDescriptor> overridables =
291                        extractMembersOverridableInBothWays(notOverriddenFromSuper, fromSuperQueue, sink);
292                createAndBindFakeOverride(overridables, current, sink);
293            }
294        }
295    
296        private static boolean isMoreSpecific(@NotNull CallableMemberDescriptor a, @NotNull CallableMemberDescriptor b) {
297            if (a instanceof SimpleFunctionDescriptor) {
298                assert b instanceof SimpleFunctionDescriptor : "b is " + b.getClass();
299    
300                KotlinType aReturnType = a.getReturnType();
301                assert aReturnType != null;
302                KotlinType bReturnType = b.getReturnType();
303                assert bReturnType != null;
304    
305                return KotlinTypeChecker.DEFAULT.isSubtypeOf(aReturnType, bReturnType);
306            }
307            if (a instanceof PropertyDescriptor) {
308                assert b instanceof PropertyDescriptor : "b is " + b.getClass();
309    
310                if (((PropertyDescriptor) a).isVar() || ((PropertyDescriptor) b).isVar()) {
311                    return ((PropertyDescriptor) a).isVar();
312                }
313    
314                // both vals
315                return KotlinTypeChecker.DEFAULT.isSubtypeOf(((PropertyDescriptor) a).getType(), ((PropertyDescriptor) b).getType());
316            }
317            throw new IllegalArgumentException("Unexpected callable: " + a.getClass());
318        }
319    
320        private static CallableMemberDescriptor selectMostSpecificMemberFromSuper(@NotNull Collection<CallableMemberDescriptor> overridables) {
321            CallableMemberDescriptor result = null;
322            for (CallableMemberDescriptor overridable : overridables) {
323                if (result == null || isMoreSpecific(overridable, result)) {
324                    result = overridable;
325                }
326            }
327            return result;
328        }
329    
330        private static void createAndBindFakeOverride(
331                @NotNull Collection<CallableMemberDescriptor> overridables,
332                @NotNull ClassDescriptor current,
333                @NotNull DescriptorSink sink
334        ) {
335            Collection<CallableMemberDescriptor> visibleOverridables = filterVisibleFakeOverrides(current, overridables);
336            boolean allInvisible = visibleOverridables.isEmpty();
337            Collection<CallableMemberDescriptor> effectiveOverridden = allInvisible ? overridables : visibleOverridables;
338    
339            Modality modality = getMinimalModality(effectiveOverridden);
340            Visibility visibility = allInvisible ? Visibilities.INVISIBLE_FAKE : Visibilities.INHERITED;
341            CallableMemberDescriptor mostSpecific = selectMostSpecificMemberFromSuper(effectiveOverridden);
342            CallableMemberDescriptor fakeOverride =
343                    mostSpecific.copy(current, modality, visibility, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false);
344            for (CallableMemberDescriptor descriptor : effectiveOverridden) {
345                fakeOverride.addOverriddenDescriptor(descriptor);
346            }
347            sink.addFakeOverride(fakeOverride);
348        }
349    
350        @NotNull
351        private static Modality getMinimalModality(@NotNull Collection<CallableMemberDescriptor> descriptors) {
352            Modality modality = Modality.ABSTRACT;
353            for (CallableMemberDescriptor descriptor : descriptors) {
354                if (descriptor.getModality().compareTo(modality) < 0) {
355                    modality = descriptor.getModality();
356                }
357            }
358            return modality;
359        }
360    
361        @NotNull
362        private static Collection<CallableMemberDescriptor> filterVisibleFakeOverrides(
363                @NotNull final ClassDescriptor current,
364                @NotNull Collection<CallableMemberDescriptor> toFilter
365        ) {
366            return CollectionsKt.filter(toFilter, new Function1<CallableMemberDescriptor, Boolean>() {
367                @Override
368                public Boolean invoke(CallableMemberDescriptor descriptor) {
369                    //nested class could capture private member, so check for private visibility added
370                    return !Visibilities.isPrivate(descriptor.getVisibility()) &&
371                           Visibilities.isVisible(ReceiverValue.IRRELEVANT_RECEIVER, descriptor, current);
372                }
373            });
374        }
375    
376        @NotNull
377        private static Collection<CallableMemberDescriptor> extractMembersOverridableInBothWays(
378                @NotNull CallableMemberDescriptor overrider,
379                @NotNull Queue<CallableMemberDescriptor> extractFrom,
380                @NotNull DescriptorSink sink
381        ) {
382            Collection<CallableMemberDescriptor> overridable = new ArrayList<CallableMemberDescriptor>();
383            overridable.add(overrider);
384            for (Iterator<CallableMemberDescriptor> iterator = extractFrom.iterator(); iterator.hasNext(); ) {
385                CallableMemberDescriptor candidate = iterator.next();
386                if (overrider == candidate) {
387                    iterator.remove();
388                    continue;
389                }
390    
391                OverrideCompatibilityInfo.Result result1 = DEFAULT.isOverridableBy(candidate, overrider).getResult();
392                OverrideCompatibilityInfo.Result result2 = DEFAULT.isOverridableBy(overrider, candidate).getResult();
393                if (result1 == OVERRIDABLE && result2 == OVERRIDABLE) {
394                    overridable.add(candidate);
395                    iterator.remove();
396                }
397                else if (result1 == CONFLICT || result2 == CONFLICT) {
398                    sink.conflict(overrider, candidate);
399                    iterator.remove();
400                }
401            }
402            return overridable;
403        }
404    
405        public static void resolveUnknownVisibilityForMember(
406                @NotNull CallableMemberDescriptor memberDescriptor,
407                @Nullable Function1<CallableMemberDescriptor, Unit> cannotInferVisibility
408        ) {
409            for (CallableMemberDescriptor descriptor : memberDescriptor.getOverriddenDescriptors()) {
410                if (descriptor.getVisibility() == Visibilities.INHERITED) {
411                    resolveUnknownVisibilityForMember(descriptor, cannotInferVisibility);
412                }
413            }
414    
415            if (memberDescriptor.getVisibility() != Visibilities.INHERITED) {
416                return;
417            }
418    
419            Visibility maxVisibility = computeVisibilityToInherit(memberDescriptor);
420            Visibility visibilityToInherit;
421            if (maxVisibility == null) {
422                if (cannotInferVisibility != null) {
423                    cannotInferVisibility.invoke(memberDescriptor);
424                }
425                visibilityToInherit = Visibilities.PUBLIC;
426            }
427            else {
428                visibilityToInherit = maxVisibility;
429            }
430    
431            if (memberDescriptor instanceof PropertyDescriptorImpl) {
432                ((PropertyDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit);
433                for (PropertyAccessorDescriptor accessor : ((PropertyDescriptor) memberDescriptor).getAccessors()) {
434                    // If we couldn't infer visibility for property, the diagnostic is already reported, no need to report it again on accessors
435                    resolveUnknownVisibilityForMember(accessor, maxVisibility == null ? null : cannotInferVisibility);
436                }
437            }
438            else if (memberDescriptor instanceof FunctionDescriptorImpl) {
439                ((FunctionDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit);
440            }
441            else {
442                assert memberDescriptor instanceof PropertyAccessorDescriptorImpl;
443                ((PropertyAccessorDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit);
444            }
445        }
446    
447        @Nullable
448        private static Visibility computeVisibilityToInherit(@NotNull CallableMemberDescriptor memberDescriptor) {
449            Collection<? extends CallableMemberDescriptor> overriddenDescriptors = memberDescriptor.getOverriddenDescriptors();
450            Visibility maxVisibility = findMaxVisibility(overriddenDescriptors);
451            if (maxVisibility == null) {
452                return null;
453            }
454            if (memberDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
455                for (CallableMemberDescriptor overridden : overriddenDescriptors) {
456                    // An implementation (a non-abstract overridden member) of a fake override should have the maximum possible visibility
457                    if (overridden.getModality() != Modality.ABSTRACT && !overridden.getVisibility().equals(maxVisibility)) {
458                        return null;
459                    }
460                }
461                return maxVisibility;
462            }
463            return maxVisibility.normalize();
464        }
465    
466        @Nullable
467        public static Visibility findMaxVisibility(@NotNull Collection<? extends CallableMemberDescriptor> descriptors) {
468            if (descriptors.isEmpty()) {
469                return Visibilities.DEFAULT_VISIBILITY;
470            }
471            Visibility maxVisibility = null;
472            for (CallableMemberDescriptor descriptor : descriptors) {
473                Visibility visibility = descriptor.getVisibility();
474                assert visibility != Visibilities.INHERITED : "Visibility should have been computed for " + descriptor;
475                if (maxVisibility == null) {
476                    maxVisibility = visibility;
477                    continue;
478                }
479                Integer compareResult = Visibilities.compare(visibility, maxVisibility);
480                if (compareResult == null) {
481                    maxVisibility = null;
482                }
483                else if (compareResult > 0) {
484                    maxVisibility = visibility;
485                }
486            }
487            // TODO: IDEA seems to issue an incorrect warning here
488            //noinspection ConstantConditions
489            if (maxVisibility == null) {
490                return null;
491            }
492            for (CallableMemberDescriptor descriptor : descriptors) {
493                Integer compareResult = Visibilities.compare(maxVisibility, descriptor.getVisibility());
494                if (compareResult == null || compareResult < 0) {
495                    return null;
496                }
497            }
498            return maxVisibility;
499        }
500    
501        @NotNull
502        public static List<? extends CallableDescriptor> getTopmostOverridenDescriptors(@NotNull CallableDescriptor originalDescriptor) {
503            return DFS.dfs(
504                    Collections.singletonList(originalDescriptor),
505                    new DFS.Neighbors<CallableDescriptor>() {
506                        @NotNull
507                        @Override
508                        public Iterable<? extends CallableDescriptor> getNeighbors(CallableDescriptor current) {
509                            return current.getOverriddenDescriptors();
510                        }
511                    },
512                    new DFS.CollectingNodeHandler<CallableDescriptor, CallableDescriptor, ArrayList<CallableDescriptor>>(
513                            new ArrayList<CallableDescriptor>()
514                    ) {
515                        @Override
516                        public void afterChildren(CallableDescriptor current) {
517                            if (current.getOverriddenDescriptors().isEmpty()) {
518                                result.add(current);
519                            }
520                        }
521                    }
522            );
523        }
524    
525        public interface DescriptorSink {
526            void addFakeOverride(@NotNull CallableMemberDescriptor fakeOverride);
527    
528            void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent);
529        }
530    
531        public static class OverrideCompatibilityInfo {
532    
533            public enum Result {
534                OVERRIDABLE,
535                INCOMPATIBLE,
536                CONFLICT,
537            }
538    
539            private static final OverrideCompatibilityInfo SUCCESS = new OverrideCompatibilityInfo(Result.OVERRIDABLE, "SUCCESS");
540    
541            @NotNull
542            public static OverrideCompatibilityInfo success() {
543                return SUCCESS;
544            }
545    
546            @NotNull
547            public static OverrideCompatibilityInfo nameMismatch() {
548                return new OverrideCompatibilityInfo(INCOMPATIBLE, "nameMismatch"); // TODO
549            }
550    
551            @NotNull
552            public static OverrideCompatibilityInfo typeParameterNumberMismatch() {
553                return new OverrideCompatibilityInfo(INCOMPATIBLE, "typeParameterNumberMismatch"); // TODO
554            }
555    
556            @NotNull
557            public static OverrideCompatibilityInfo receiverPresenceMismatch() {
558                return new OverrideCompatibilityInfo(INCOMPATIBLE, "receiverPresenceMismatch"); // TODO
559            }
560    
561            @NotNull
562            public static OverrideCompatibilityInfo valueParameterNumberMismatch() {
563                return new OverrideCompatibilityInfo(INCOMPATIBLE, "valueParameterNumberMismatch"); // TODO
564            }
565    
566            @NotNull
567            public static OverrideCompatibilityInfo boundsMismatch(TypeParameterDescriptor superTypeParameter, TypeParameterDescriptor subTypeParameter) {
568                return new OverrideCompatibilityInfo(INCOMPATIBLE, "boundsMismatch"); // TODO
569            }
570    
571            @NotNull
572            public static OverrideCompatibilityInfo valueParameterTypeMismatch(KotlinType superValueParameter, KotlinType subValueParameter, Result result) {
573                return new OverrideCompatibilityInfo(result, "valueParameterTypeMismatch"); // TODO
574            }
575    
576            @NotNull
577            public static OverrideCompatibilityInfo memberKindMismatch() {
578                return new OverrideCompatibilityInfo(INCOMPATIBLE, "memberKindMismatch"); // TODO
579            }
580    
581            @NotNull
582            public static OverrideCompatibilityInfo returnTypeMismatch(KotlinType substitutedSuperReturnType, KotlinType unsubstitutedSubReturnType) {
583                return new OverrideCompatibilityInfo(Result.CONFLICT, "returnTypeMismatch: " + unsubstitutedSubReturnType + " >< " + substitutedSuperReturnType); // TODO
584            }
585    
586            @NotNull
587            public static OverrideCompatibilityInfo varOverriddenByVal() {
588                return new OverrideCompatibilityInfo(INCOMPATIBLE, "varOverriddenByVal"); // TODO
589            }
590    
591            @NotNull
592            public static OverrideCompatibilityInfo externalConditionFailed(Class<? extends ExternalOverridabilityCondition> conditionClass) {
593                return new OverrideCompatibilityInfo(INCOMPATIBLE, "externalConditionFailed: " + conditionClass.getName()); // TODO
594            }
595    
596            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
597    
598            private final Result overridable;
599            private final String message;
600    
601            public OverrideCompatibilityInfo(Result success, String message) {
602                this.overridable = success;
603                this.message = message;
604            }
605    
606            public Result getResult() {
607                return overridable;
608            }
609    
610            public String getMessage() {
611                return message;
612            }
613        }
614    }