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 generateOverridesInFunctionGroup( 234 @SuppressWarnings("UnusedParameters") 235 @NotNull Name name, //DO NOT DELETE THIS PARAMETER: needed to make sure all descriptors have the same name 236 @NotNull Collection<? extends CallableMemberDescriptor> membersFromSupertypes, 237 @NotNull Collection<? extends CallableMemberDescriptor> membersFromCurrent, 238 @NotNull ClassDescriptor current, 239 @NotNull DescriptorSink sink 240 ) { 241 Collection<CallableMemberDescriptor> notOverridden = new LinkedHashSet<CallableMemberDescriptor>(membersFromSupertypes); 242 243 for (CallableMemberDescriptor fromCurrent : membersFromCurrent) { 244 Collection<CallableMemberDescriptor> bound = 245 extractAndBindOverridesForMember(fromCurrent, membersFromSupertypes, current, sink); 246 notOverridden.removeAll(bound); 247 } 248 249 createAndBindFakeOverrides(current, notOverridden, sink); 250 } 251 252 private static Collection<CallableMemberDescriptor> extractAndBindOverridesForMember( 253 @NotNull CallableMemberDescriptor fromCurrent, 254 @NotNull Collection<? extends CallableMemberDescriptor> descriptorsFromSuper, 255 @NotNull ClassDescriptor current, 256 @NotNull DescriptorSink sink 257 ) { 258 Collection<CallableMemberDescriptor> bound = new ArrayList<CallableMemberDescriptor>(descriptorsFromSuper.size()); 259 for (CallableMemberDescriptor fromSupertype : descriptorsFromSuper) { 260 OverrideCompatibilityInfo.Result result = DEFAULT.isOverridableBy(fromSupertype, fromCurrent).getResult(); 261 262 boolean isVisible = Visibilities.isVisible(ReceiverValue.IRRELEVANT_RECEIVER, fromSupertype, current); 263 switch (result) { 264 case OVERRIDABLE: 265 if (isVisible) { 266 fromCurrent.addOverriddenDescriptor(fromSupertype); 267 } 268 bound.add(fromSupertype); 269 break; 270 case CONFLICT: 271 if (isVisible) { 272 sink.conflict(fromSupertype, fromCurrent); 273 } 274 bound.add(fromSupertype); 275 break; 276 case INCOMPATIBLE: 277 break; 278 } 279 } 280 return bound; 281 } 282 283 private static void createAndBindFakeOverrides( 284 @NotNull ClassDescriptor current, 285 @NotNull Collection<CallableMemberDescriptor> notOverridden, 286 @NotNull DescriptorSink sink 287 ) { 288 Queue<CallableMemberDescriptor> fromSuperQueue = new LinkedList<CallableMemberDescriptor>(notOverridden); 289 while (!fromSuperQueue.isEmpty()) { 290 CallableMemberDescriptor notOverriddenFromSuper = VisibilityUtil.findMemberWithMaxVisibility(fromSuperQueue); 291 Collection<CallableMemberDescriptor> overridables = 292 extractMembersOverridableInBothWays(notOverriddenFromSuper, fromSuperQueue, sink); 293 createAndBindFakeOverride(overridables, current, sink); 294 } 295 } 296 297 private static boolean isMoreSpecific(@NotNull CallableMemberDescriptor a, @NotNull CallableMemberDescriptor b) { 298 if (a instanceof SimpleFunctionDescriptor) { 299 assert b instanceof SimpleFunctionDescriptor : "b is " + b.getClass(); 300 301 JetType aReturnType = a.getReturnType(); 302 assert aReturnType != null; 303 JetType bReturnType = b.getReturnType(); 304 assert bReturnType != null; 305 306 return JetTypeChecker.DEFAULT.isSubtypeOf(aReturnType, bReturnType); 307 } 308 if (a instanceof PropertyDescriptor) { 309 assert b instanceof PropertyDescriptor : "b is " + b.getClass(); 310 311 if (((PropertyDescriptor) a).isVar() || ((PropertyDescriptor) b).isVar()) { 312 return ((PropertyDescriptor) a).isVar(); 313 } 314 315 // both vals 316 return JetTypeChecker.DEFAULT.isSubtypeOf(((PropertyDescriptor) a).getType(), ((PropertyDescriptor) b).getType()); 317 } 318 throw new IllegalArgumentException("Unexpected callable: " + a.getClass()); 319 } 320 321 private static CallableMemberDescriptor selectMostSpecificMemberFromSuper(@NotNull Collection<CallableMemberDescriptor> overridables) { 322 CallableMemberDescriptor result = null; 323 for (CallableMemberDescriptor overridable : overridables) { 324 if (result == null || isMoreSpecific(overridable, result)) { 325 result = overridable; 326 } 327 } 328 return result; 329 } 330 331 private static void createAndBindFakeOverride( 332 @NotNull Collection<CallableMemberDescriptor> overridables, 333 @NotNull ClassDescriptor current, 334 @NotNull DescriptorSink sink 335 ) { 336 Collection<CallableMemberDescriptor> visibleOverridables = filterVisibleFakeOverrides(current, overridables); 337 boolean allInvisible = visibleOverridables.isEmpty(); 338 Collection<CallableMemberDescriptor> effectiveOverridden = allInvisible ? overridables : visibleOverridables; 339 340 Modality modality = getMinimalModality(effectiveOverridden); 341 Visibility visibility = allInvisible ? Visibilities.INVISIBLE_FAKE : Visibilities.INHERITED; 342 CallableMemberDescriptor mostSpecific = selectMostSpecificMemberFromSuper(effectiveOverridden); 343 CallableMemberDescriptor fakeOverride = 344 mostSpecific.copy(current, modality, visibility, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false); 345 for (CallableMemberDescriptor descriptor : effectiveOverridden) { 346 fakeOverride.addOverriddenDescriptor(descriptor); 347 } 348 sink.addFakeOverride(fakeOverride); 349 } 350 351 @NotNull 352 private static Modality getMinimalModality(@NotNull Collection<CallableMemberDescriptor> descriptors) { 353 Modality modality = Modality.ABSTRACT; 354 for (CallableMemberDescriptor descriptor : descriptors) { 355 if (descriptor.getModality().compareTo(modality) < 0) { 356 modality = descriptor.getModality(); 357 } 358 } 359 return modality; 360 } 361 362 @NotNull 363 private static Collection<CallableMemberDescriptor> filterVisibleFakeOverrides( 364 @NotNull final ClassDescriptor current, 365 @NotNull Collection<CallableMemberDescriptor> toFilter 366 ) { 367 return KotlinPackage.filter(toFilter, new Function1<CallableMemberDescriptor, Boolean>() { 368 @Override 369 public Boolean invoke(CallableMemberDescriptor descriptor) { 370 //nested class could capture private member, so check for private visibility added 371 return !Visibilities.isPrivate(descriptor.getVisibility()) && 372 Visibilities.isVisible(ReceiverValue.IRRELEVANT_RECEIVER, descriptor, current); 373 } 374 }); 375 } 376 377 @NotNull 378 private static Collection<CallableMemberDescriptor> extractMembersOverridableInBothWays( 379 @NotNull CallableMemberDescriptor overrider, 380 @NotNull Queue<CallableMemberDescriptor> extractFrom, 381 @NotNull DescriptorSink sink 382 ) { 383 Collection<CallableMemberDescriptor> overridable = new ArrayList<CallableMemberDescriptor>(); 384 overridable.add(overrider); 385 for (Iterator<CallableMemberDescriptor> iterator = extractFrom.iterator(); iterator.hasNext(); ) { 386 CallableMemberDescriptor candidate = iterator.next(); 387 if (overrider == candidate) { 388 iterator.remove(); 389 continue; 390 } 391 392 OverrideCompatibilityInfo.Result result1 = DEFAULT.isOverridableBy(candidate, overrider).getResult(); 393 OverrideCompatibilityInfo.Result result2 = DEFAULT.isOverridableBy(overrider, candidate).getResult(); 394 if (result1 == OVERRIDABLE && result2 == OVERRIDABLE) { 395 overridable.add(candidate); 396 iterator.remove(); 397 } 398 else if (result1 == CONFLICT || result2 == CONFLICT) { 399 sink.conflict(overrider, candidate); 400 iterator.remove(); 401 } 402 } 403 return overridable; 404 } 405 406 public static void resolveUnknownVisibilityForMember( 407 @NotNull CallableMemberDescriptor memberDescriptor, 408 @Nullable Function1<CallableMemberDescriptor, Unit> cannotInferVisibility 409 ) { 410 for (CallableMemberDescriptor descriptor : memberDescriptor.getOverriddenDescriptors()) { 411 if (descriptor.getVisibility() == Visibilities.INHERITED) { 412 resolveUnknownVisibilityForMember(descriptor, cannotInferVisibility); 413 } 414 } 415 416 if (memberDescriptor.getVisibility() != Visibilities.INHERITED) { 417 return; 418 } 419 420 Visibility maxVisibility = computeVisibilityToInherit(memberDescriptor); 421 Visibility visibilityToInherit; 422 if (maxVisibility == null) { 423 if (cannotInferVisibility != null) { 424 cannotInferVisibility.invoke(memberDescriptor); 425 } 426 visibilityToInherit = Visibilities.PUBLIC; 427 } 428 else { 429 visibilityToInherit = maxVisibility; 430 } 431 432 if (memberDescriptor instanceof PropertyDescriptorImpl) { 433 ((PropertyDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit); 434 for (PropertyAccessorDescriptor accessor : ((PropertyDescriptor) memberDescriptor).getAccessors()) { 435 // If we couldn't infer visibility for property, the diagnostic is already reported, no need to report it again on accessors 436 resolveUnknownVisibilityForMember(accessor, maxVisibility == null ? null : cannotInferVisibility); 437 } 438 } 439 else if (memberDescriptor instanceof FunctionDescriptorImpl) { 440 ((FunctionDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit); 441 } 442 else { 443 assert memberDescriptor instanceof PropertyAccessorDescriptorImpl; 444 ((PropertyAccessorDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit); 445 } 446 } 447 448 @Nullable 449 private static Visibility computeVisibilityToInherit(@NotNull CallableMemberDescriptor memberDescriptor) { 450 Collection<? extends CallableMemberDescriptor> overriddenDescriptors = memberDescriptor.getOverriddenDescriptors(); 451 Visibility maxVisibility = findMaxVisibility(overriddenDescriptors); 452 if (maxVisibility == null) { 453 return null; 454 } 455 if (memberDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { 456 for (CallableMemberDescriptor overridden : overriddenDescriptors) { 457 // An implementation (a non-abstract overridden member) of a fake override should have the maximum possible visibility 458 if (overridden.getModality() != Modality.ABSTRACT && !overridden.getVisibility().equals(maxVisibility)) { 459 return null; 460 } 461 } 462 return maxVisibility; 463 } 464 return maxVisibility.normalize(); 465 } 466 467 @Nullable 468 public static Visibility findMaxVisibility(@NotNull Collection<? extends CallableMemberDescriptor> descriptors) { 469 if (descriptors.isEmpty()) { 470 return Visibilities.DEFAULT_VISIBILITY; 471 } 472 Visibility maxVisibility = null; 473 for (CallableMemberDescriptor descriptor : descriptors) { 474 Visibility visibility = descriptor.getVisibility(); 475 assert visibility != Visibilities.INHERITED : "Visibility should have been computed for " + descriptor; 476 if (maxVisibility == null) { 477 maxVisibility = visibility; 478 continue; 479 } 480 Integer compareResult = Visibilities.compare(visibility, maxVisibility); 481 if (compareResult == null) { 482 maxVisibility = null; 483 } 484 else if (compareResult > 0) { 485 maxVisibility = visibility; 486 } 487 } 488 // TODO: IDEA seems to issue an incorrect warning here 489 //noinspection ConstantConditions 490 if (maxVisibility == null) { 491 return null; 492 } 493 for (CallableMemberDescriptor descriptor : descriptors) { 494 Integer compareResult = Visibilities.compare(maxVisibility, descriptor.getVisibility()); 495 if (compareResult == null || compareResult < 0) { 496 return null; 497 } 498 } 499 return maxVisibility; 500 } 501 502 503 @NotNull 504 @KotlinSignature("fun getTopmostOverridenDescriptors(originalDescriptor: CallableDescriptor): List<out CallableDescriptor>") 505 public static List<? extends CallableDescriptor> getTopmostOverridenDescriptors(@NotNull CallableDescriptor originalDescriptor) { 506 return DFS.dfs( 507 Collections.singletonList(originalDescriptor), 508 new DFS.Neighbors<CallableDescriptor>() { 509 @NotNull 510 @Override 511 public Iterable<? extends CallableDescriptor> getNeighbors(CallableDescriptor current) { 512 return current.getOverriddenDescriptors(); 513 } 514 }, 515 new DFS.CollectingNodeHandler<CallableDescriptor, CallableDescriptor, ArrayList<CallableDescriptor>>( 516 new ArrayList<CallableDescriptor>() 517 ) { 518 @Override 519 public void afterChildren(CallableDescriptor current) { 520 if (current.getOverriddenDescriptors().isEmpty()) { 521 result.add(current); 522 } 523 } 524 } 525 ); 526 } 527 528 public static boolean traverseOverridenDescriptors( 529 @NotNull CallableDescriptor originalDescriptor, 530 @NotNull final Function1<CallableDescriptor, Boolean> handler 531 ) { 532 return DFS.dfs( 533 Collections.singletonList(originalDescriptor), 534 new DFS.Neighbors<CallableDescriptor>() { 535 @NotNull 536 @Override 537 public Iterable<? extends CallableDescriptor> getNeighbors(CallableDescriptor current) { 538 return current.getOverriddenDescriptors(); 539 } 540 }, 541 new DFS.AbstractNodeHandler<CallableDescriptor, Boolean>() { 542 private boolean result = true; 543 544 @Override 545 public boolean beforeChildren(CallableDescriptor current) { 546 if (!handler.invoke(current)) { 547 result = false; 548 } 549 return result; 550 } 551 552 @Override 553 public Boolean result() { 554 return result; 555 } 556 } 557 ); 558 } 559 560 public interface DescriptorSink { 561 void addFakeOverride(@NotNull CallableMemberDescriptor fakeOverride); 562 563 void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent); 564 } 565 566 public static class OverrideCompatibilityInfo { 567 568 public enum Result { 569 OVERRIDABLE, 570 INCOMPATIBLE, 571 CONFLICT, 572 } 573 574 private static final OverrideCompatibilityInfo SUCCESS = new OverrideCompatibilityInfo(Result.OVERRIDABLE, "SUCCESS"); 575 576 @NotNull 577 public static OverrideCompatibilityInfo success() { 578 return SUCCESS; 579 } 580 581 @NotNull 582 public static OverrideCompatibilityInfo nameMismatch() { 583 return new OverrideCompatibilityInfo(INCOMPATIBLE, "nameMismatch"); // TODO 584 } 585 586 @NotNull 587 public static OverrideCompatibilityInfo typeParameterNumberMismatch() { 588 return new OverrideCompatibilityInfo(INCOMPATIBLE, "typeParameterNumberMismatch"); // TODO 589 } 590 591 @NotNull 592 public static OverrideCompatibilityInfo receiverPresenceMismatch() { 593 return new OverrideCompatibilityInfo(INCOMPATIBLE, "receiverPresenceMismatch"); // TODO 594 } 595 596 @NotNull 597 public static OverrideCompatibilityInfo valueParameterNumberMismatch() { 598 return new OverrideCompatibilityInfo(INCOMPATIBLE, "valueParameterNumberMismatch"); // TODO 599 } 600 601 @NotNull 602 public static OverrideCompatibilityInfo boundsMismatch(TypeParameterDescriptor superTypeParameter, TypeParameterDescriptor subTypeParameter) { 603 return new OverrideCompatibilityInfo(INCOMPATIBLE, "boundsMismatch"); // TODO 604 } 605 606 @NotNull 607 public static OverrideCompatibilityInfo valueParameterTypeMismatch(JetType superValueParameter, JetType subValueParameter, Result result) { 608 return new OverrideCompatibilityInfo(result, "valueParameterTypeMismatch"); // TODO 609 } 610 611 @NotNull 612 public static OverrideCompatibilityInfo memberKindMismatch() { 613 return new OverrideCompatibilityInfo(INCOMPATIBLE, "memberKindMismatch"); // TODO 614 } 615 616 @NotNull 617 public static OverrideCompatibilityInfo returnTypeMismatch(JetType substitutedSuperReturnType, JetType unsubstitutedSubReturnType) { 618 return new OverrideCompatibilityInfo(Result.CONFLICT, "returnTypeMismatch: " + unsubstitutedSubReturnType + " >< " + substitutedSuperReturnType); // TODO 619 } 620 621 @NotNull 622 public static OverrideCompatibilityInfo varOverriddenByVal() { 623 return new OverrideCompatibilityInfo(INCOMPATIBLE, "varOverriddenByVal"); // TODO 624 } 625 626 @NotNull 627 public static OverrideCompatibilityInfo externalConditionFailed(Class<? extends ExternalOverridabilityCondition> conditionClass) { 628 return new OverrideCompatibilityInfo(INCOMPATIBLE, "externalConditionFailed: " + conditionClass.getName()); // TODO 629 } 630 631 //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 632 633 private final Result overridable; 634 private final String message; 635 636 public OverrideCompatibilityInfo(Result success, String message) { 637 this.overridable = success; 638 this.message = message; 639 } 640 641 public Result getResult() { 642 return overridable; 643 } 644 645 public String getMessage() { 646 return message; 647 } 648 } 649 }