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.Function1; 020 import kotlin.KotlinPackage; 021 import kotlin.Unit; 022 import kotlin.jvm.KotlinSignature; 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 }