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