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.collections.CollectionsKt; 020 import kotlin.Unit; 021 import kotlin.jvm.functions.Function1; 022 import org.jetbrains.annotations.Mutable; 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.types.FlexibleTypesKt; 031 import org.jetbrains.kotlin.types.KotlinType; 032 import org.jetbrains.kotlin.types.TypeConstructor; 033 import org.jetbrains.kotlin.types.checker.KotlinTypeChecker; 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( 067 @NotNull CallableDescriptor superDescriptor, 068 @NotNull CallableDescriptor subDescriptor, 069 @Nullable ClassDescriptor subClassDescriptor 070 ) { 071 return isOverridableBy(superDescriptor, subDescriptor, subClassDescriptor, false); 072 } 073 074 @NotNull 075 public OverrideCompatibilityInfo isOverridableByIncludingReturnType(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) { 076 return isOverridableBy(superDescriptor, subDescriptor, null, true); 077 } 078 079 @NotNull 080 private OverrideCompatibilityInfo isOverridableBy( 081 @NotNull CallableDescriptor superDescriptor, 082 @NotNull CallableDescriptor subDescriptor, 083 @Nullable ClassDescriptor subClassDescriptor, 084 boolean checkReturnType 085 ) { 086 boolean wasSuccessfulExternalCondition = false; 087 for (ExternalOverridabilityCondition externalCondition : EXTERNAL_CONDITIONS) { 088 ExternalOverridabilityCondition.Result result = 089 externalCondition.isOverridable(superDescriptor, subDescriptor, subClassDescriptor); 090 switch (result) { 091 case OVERRIDABLE: 092 wasSuccessfulExternalCondition = true; 093 break; 094 case CONFLICT: 095 return OverrideCompatibilityInfo.conflict("External condition failed"); 096 case INCOMPATIBLE: 097 return OverrideCompatibilityInfo.incompatible("External condition"); 098 case UNKNOWN: 099 // do nothing 100 // go to the next external condition or default override check 101 } 102 } 103 104 if (wasSuccessfulExternalCondition) { 105 return OverrideCompatibilityInfo.success(); 106 } 107 108 return isOverridableByWithoutExternalConditions(superDescriptor, subDescriptor, checkReturnType); 109 } 110 111 @NotNull 112 public OverrideCompatibilityInfo isOverridableByWithoutExternalConditions( 113 @NotNull CallableDescriptor superDescriptor, 114 @NotNull CallableDescriptor subDescriptor, 115 boolean checkReturnType 116 ) { 117 if (superDescriptor instanceof FunctionDescriptor && !(subDescriptor instanceof FunctionDescriptor) || 118 superDescriptor instanceof PropertyDescriptor && !(subDescriptor instanceof PropertyDescriptor)) { 119 return OverrideCompatibilityInfo.incompatible("Member kind mismatch"); 120 } 121 122 if (!(superDescriptor instanceof FunctionDescriptor) && !(superDescriptor instanceof PropertyDescriptor)) { 123 throw new IllegalArgumentException("This type of CallableDescriptor cannot be checked for overridability: " + superDescriptor); 124 } 125 126 // TODO: check outside of this method 127 if (!superDescriptor.getName().equals(subDescriptor.getName())) { 128 return OverrideCompatibilityInfo.incompatible("Name mismatch"); 129 } 130 131 OverrideCompatibilityInfo receiverAndParameterResult = checkReceiverAndParameterCount(superDescriptor, subDescriptor); 132 if (receiverAndParameterResult != null) { 133 return receiverAndParameterResult; 134 } 135 136 List<KotlinType> superValueParameters = compiledValueParameters(superDescriptor); 137 List<KotlinType> subValueParameters = compiledValueParameters(subDescriptor); 138 139 List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters(); 140 List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters(); 141 142 if (superTypeParameters.size() != subTypeParameters.size()) { 143 for (int i = 0; i < superValueParameters.size(); ++i) { 144 // TODO: compare erasure 145 if (!KotlinTypeChecker.DEFAULT.equalTypes(superValueParameters.get(i), subValueParameters.get(i))) { 146 return OverrideCompatibilityInfo.incompatible("Type parameter number mismatch"); 147 } 148 } 149 return OverrideCompatibilityInfo.conflict("Type parameter number mismatch"); 150 } 151 152 KotlinTypeChecker typeChecker = createTypeChecker(superTypeParameters, subTypeParameters); 153 154 for (int i = 0; i < superTypeParameters.size(); i++) { 155 if (!areTypeParametersEquivalent(superTypeParameters.get(i), subTypeParameters.get(i), typeChecker)) { 156 return OverrideCompatibilityInfo.incompatible("Type parameter bounds mismatch"); 157 } 158 } 159 160 for (int i = 0; i < superValueParameters.size(); i++) { 161 if (!areTypesEquivalent(superValueParameters.get(i), subValueParameters.get(i), typeChecker)) { 162 return OverrideCompatibilityInfo.incompatible("Value parameter type mismatch"); 163 } 164 } 165 166 if (checkReturnType) { 167 KotlinType superReturnType = superDescriptor.getReturnType(); 168 KotlinType subReturnType = subDescriptor.getReturnType(); 169 170 if (superReturnType != null && subReturnType != null) { 171 boolean bothErrors = subReturnType.isError() && superReturnType.isError(); 172 if (!bothErrors && !typeChecker.isSubtypeOf(subReturnType, superReturnType)) { 173 return OverrideCompatibilityInfo.conflict("Return type mismatch"); 174 } 175 } 176 } 177 178 return OverrideCompatibilityInfo.success(); 179 } 180 181 @NotNull 182 private KotlinTypeChecker createTypeChecker( 183 @NotNull List<TypeParameterDescriptor> firstParameters, 184 @NotNull List<TypeParameterDescriptor> secondParameters 185 ) { 186 assert firstParameters.size() == secondParameters.size() : 187 "Should be the same number of type parameters: " + firstParameters + " vs " + secondParameters; 188 if (firstParameters.isEmpty()) return KotlinTypeChecker.withAxioms(equalityAxioms); 189 190 final Map<TypeConstructor, TypeConstructor> matchingTypeConstructors = new HashMap<TypeConstructor, TypeConstructor>(); 191 for (int i = 0; i < firstParameters.size(); i++) { 192 matchingTypeConstructors.put(firstParameters.get(i).getTypeConstructor(), secondParameters.get(i).getTypeConstructor()); 193 } 194 195 return KotlinTypeChecker.withAxioms(new KotlinTypeChecker.TypeConstructorEquality() { 196 @Override 197 public boolean equals(@NotNull TypeConstructor a, @NotNull TypeConstructor b) { 198 if (equalityAxioms.equals(a, b)) return true; 199 TypeConstructor img1 = matchingTypeConstructors.get(a); 200 TypeConstructor img2 = matchingTypeConstructors.get(b); 201 return (img1 != null && img1.equals(b)) || (img2 != null && img2.equals(a)); 202 } 203 }); 204 } 205 206 @Nullable 207 static OverrideCompatibilityInfo checkReceiverAndParameterCount( 208 CallableDescriptor superDescriptor, 209 CallableDescriptor subDescriptor 210 ) { 211 if ((superDescriptor.getExtensionReceiverParameter() == null) != (subDescriptor.getExtensionReceiverParameter() == null)) { 212 return OverrideCompatibilityInfo.incompatible("Receiver presence mismatch"); 213 } 214 215 if (superDescriptor.getValueParameters().size() != subDescriptor.getValueParameters().size()) { 216 return OverrideCompatibilityInfo.incompatible("Value parameter number mismatch"); 217 } 218 219 return null; 220 } 221 222 private static boolean areTypesEquivalent( 223 @NotNull KotlinType typeInSuper, 224 @NotNull KotlinType typeInSub, 225 @NotNull KotlinTypeChecker typeChecker 226 ) { 227 boolean bothErrors = typeInSuper.isError() && typeInSub.isError(); 228 return bothErrors || typeChecker.equalTypes(typeInSuper, typeInSub); 229 } 230 231 // See JLS 8, 8.4.4 Generic Methods 232 // TODO: use TypeSubstitutor instead 233 private static boolean areTypeParametersEquivalent( 234 @NotNull TypeParameterDescriptor superTypeParameter, 235 @NotNull TypeParameterDescriptor subTypeParameter, 236 @NotNull KotlinTypeChecker typeChecker 237 ) { 238 List<KotlinType> superBounds = superTypeParameter.getUpperBounds(); 239 List<KotlinType> subBounds = new ArrayList<KotlinType>(subTypeParameter.getUpperBounds()); 240 if (superBounds.size() != subBounds.size()) return false; 241 242 outer: 243 for (KotlinType superBound : superBounds) { 244 ListIterator<KotlinType> it = subBounds.listIterator(); 245 while (it.hasNext()) { 246 KotlinType subBound = it.next(); 247 if (areTypesEquivalent(superBound, subBound, typeChecker)) { 248 it.remove(); 249 continue outer; 250 } 251 } 252 return false; 253 } 254 255 return true; 256 } 257 258 static List<KotlinType> compiledValueParameters(CallableDescriptor callableDescriptor) { 259 ReceiverParameterDescriptor receiverParameter = callableDescriptor.getExtensionReceiverParameter(); 260 List<KotlinType> parameters = new ArrayList<KotlinType>(); 261 if (receiverParameter != null) { 262 parameters.add(receiverParameter.getType()); 263 } 264 for (ValueParameterDescriptor valueParameterDescriptor : callableDescriptor.getValueParameters()) { 265 parameters.add(valueParameterDescriptor.getType()); 266 } 267 return parameters; 268 } 269 270 public static void generateOverridesInFunctionGroup( 271 @SuppressWarnings("UnusedParameters") 272 @NotNull Name name, //DO NOT DELETE THIS PARAMETER: needed to make sure all descriptors have the same name 273 @NotNull Collection<? extends CallableMemberDescriptor> membersFromSupertypes, 274 @NotNull Collection<? extends CallableMemberDescriptor> membersFromCurrent, 275 @NotNull ClassDescriptor current, 276 @NotNull DescriptorSink sink 277 ) { 278 Collection<CallableMemberDescriptor> notOverridden = new LinkedHashSet<CallableMemberDescriptor>(membersFromSupertypes); 279 280 for (CallableMemberDescriptor fromCurrent : membersFromCurrent) { 281 Collection<CallableMemberDescriptor> bound = 282 extractAndBindOverridesForMember(fromCurrent, membersFromSupertypes, current, sink); 283 notOverridden.removeAll(bound); 284 } 285 286 createAndBindFakeOverrides(current, notOverridden, sink); 287 } 288 289 private static Collection<CallableMemberDescriptor> extractAndBindOverridesForMember( 290 @NotNull CallableMemberDescriptor fromCurrent, 291 @NotNull Collection<? extends CallableMemberDescriptor> descriptorsFromSuper, 292 @NotNull ClassDescriptor current, 293 @NotNull DescriptorSink sink 294 ) { 295 Collection<CallableMemberDescriptor> bound = new ArrayList<CallableMemberDescriptor>(descriptorsFromSuper.size()); 296 for (CallableMemberDescriptor fromSupertype : descriptorsFromSuper) { 297 OverrideCompatibilityInfo.Result result = DEFAULT.isOverridableBy(fromSupertype, fromCurrent, current).getResult(); 298 299 boolean isVisible = Visibilities.isVisibleWithIrrelevantReceiver(fromSupertype, current); 300 switch (result) { 301 case OVERRIDABLE: 302 if (isVisible) { 303 fromCurrent.addOverriddenDescriptor(fromSupertype); 304 } 305 bound.add(fromSupertype); 306 break; 307 case CONFLICT: 308 if (isVisible) { 309 sink.conflict(fromSupertype, fromCurrent); 310 } 311 bound.add(fromSupertype); 312 break; 313 case INCOMPATIBLE: 314 break; 315 } 316 } 317 return bound; 318 } 319 320 private static void createAndBindFakeOverrides( 321 @NotNull ClassDescriptor current, 322 @NotNull Collection<CallableMemberDescriptor> notOverridden, 323 @NotNull DescriptorSink sink 324 ) { 325 Queue<CallableMemberDescriptor> fromSuperQueue = new LinkedList<CallableMemberDescriptor>(notOverridden); 326 while (!fromSuperQueue.isEmpty()) { 327 CallableMemberDescriptor notOverriddenFromSuper = VisibilityUtilKt.findMemberWithMaxVisibility(fromSuperQueue); 328 Collection<CallableMemberDescriptor> overridables = 329 extractMembersOverridableInBothWays(notOverriddenFromSuper, fromSuperQueue, sink); 330 createAndBindFakeOverride(overridables, current, sink); 331 } 332 } 333 334 public static boolean isMoreSpecific(@NotNull CallableDescriptor a, @NotNull CallableDescriptor b) { 335 KotlinType aReturnType = a.getReturnType(); 336 KotlinType bReturnType = b.getReturnType(); 337 338 assert aReturnType != null : "Return type of " + a + " is null"; 339 assert bReturnType != null : "Return type of " + b + " is null"; 340 341 if (!isVisibilityMoreSpecific(a, b)) return false; 342 343 if (a instanceof SimpleFunctionDescriptor) { 344 assert b instanceof SimpleFunctionDescriptor : "b is " + b.getClass(); 345 346 return isReturnTypeMoreSpecific(a, aReturnType, b, bReturnType); 347 } 348 if (a instanceof PropertyDescriptor) { 349 assert b instanceof PropertyDescriptor : "b is " + b.getClass(); 350 351 PropertyDescriptor pa = (PropertyDescriptor) a; 352 PropertyDescriptor pb = (PropertyDescriptor) b; 353 354 if (!isAccessorMoreSpecific(pa.getSetter(), pb.getSetter())) return false; 355 356 if (pa.isVar() && pb.isVar()) { 357 return DEFAULT.createTypeChecker(a.getTypeParameters(), b.getTypeParameters()).equalTypes(aReturnType, bReturnType); 358 } 359 else { 360 // both vals or var vs val: val can't be more specific then var 361 return !(!pa.isVar() && pb.isVar()) && isReturnTypeMoreSpecific(a, aReturnType, b, bReturnType); 362 } 363 } 364 throw new IllegalArgumentException("Unexpected callable: " + a.getClass()); 365 } 366 367 private static boolean isVisibilityMoreSpecific( 368 @NotNull DeclarationDescriptorWithVisibility a, 369 @NotNull DeclarationDescriptorWithVisibility b 370 ) { 371 Integer result = Visibilities.compare(a.getVisibility(), b.getVisibility()); 372 return result == null || result >= 0; 373 } 374 375 private static boolean isAccessorMoreSpecific(@Nullable PropertyAccessorDescriptor a, @Nullable PropertyAccessorDescriptor b) { 376 if (a == null || b == null) return true; 377 return isVisibilityMoreSpecific(a, b); 378 } 379 380 private static boolean isMoreSpecificThenAllOf(@NotNull CallableDescriptor candidate, @NotNull Collection<CallableDescriptor> descriptors) { 381 // NB subtyping relation in Kotlin is not transitive in presence of flexible types: 382 // String? <: String! <: String, but not String? <: String 383 for (CallableDescriptor descriptor : descriptors) { 384 if (!isMoreSpecific(candidate, descriptor)) { 385 return false; 386 } 387 } 388 return true; 389 } 390 391 private static boolean isReturnTypeMoreSpecific( 392 @NotNull CallableDescriptor a, 393 @NotNull KotlinType aReturnType, 394 @NotNull CallableDescriptor b, 395 @NotNull KotlinType bReturnType 396 ) { 397 KotlinTypeChecker typeChecker = DEFAULT.createTypeChecker(a.getTypeParameters(), b.getTypeParameters()); 398 return typeChecker.isSubtypeOf(aReturnType, bReturnType); 399 } 400 401 @NotNull 402 public static <H> H selectMostSpecificMember( 403 @NotNull Collection<H> overridables, 404 @NotNull Function1<H, CallableDescriptor> descriptorByHandle 405 ) { 406 assert !overridables.isEmpty() : "Should have at least one overridable descriptor"; 407 408 if (overridables.size() == 1) { 409 return CollectionsKt.first(overridables); 410 } 411 412 Collection<H> candidates = new ArrayList<H>(2); 413 List<CallableDescriptor> callableMemberDescriptors = CollectionsKt.map(overridables, descriptorByHandle); 414 415 H transitivelyMostSpecific = CollectionsKt.first(overridables); 416 CallableDescriptor transitivelyMostSpecificDescriptor = descriptorByHandle.invoke(transitivelyMostSpecific); 417 418 for (H overridable : overridables) { 419 CallableDescriptor descriptor = descriptorByHandle.invoke(overridable); 420 if (isMoreSpecificThenAllOf(descriptor, callableMemberDescriptors)) { 421 candidates.add(overridable); 422 } 423 if (isMoreSpecific(descriptor, transitivelyMostSpecificDescriptor) 424 && !isMoreSpecific(transitivelyMostSpecificDescriptor, descriptor)) { 425 transitivelyMostSpecific = overridable; 426 } 427 } 428 429 if (candidates.isEmpty()) { 430 return transitivelyMostSpecific; 431 } 432 else if (candidates.size() == 1) { 433 return CollectionsKt.first(candidates); 434 } 435 436 H firstNonFlexible = null; 437 for (H candidate : candidates) { 438 if (!FlexibleTypesKt.isFlexible(descriptorByHandle.invoke(candidate).getReturnType())) { 439 firstNonFlexible = candidate; 440 break; 441 } 442 } 443 if (firstNonFlexible != null) { 444 return firstNonFlexible; 445 } 446 447 return CollectionsKt.first(candidates); 448 } 449 450 private static void createAndBindFakeOverride( 451 @NotNull Collection<CallableMemberDescriptor> overridables, 452 @NotNull ClassDescriptor current, 453 @NotNull DescriptorSink sink 454 ) { 455 Collection<CallableMemberDescriptor> visibleOverridables = filterVisibleFakeOverrides(current, overridables); 456 boolean allInvisible = visibleOverridables.isEmpty(); 457 Collection<CallableMemberDescriptor> effectiveOverridden = allInvisible ? overridables : visibleOverridables; 458 459 // FIXME doesn't work as expected for flexible types: should create a refined signature. 460 // Current algorithm produces bad results in presence of annotated Java signatures such as: 461 // J: foo(s: String!): String -- @NotNull String foo(String s); 462 // K: foo(s: String): String? 463 // --> 'foo(s: String!): String' as an inherited signature with most specific return type. 464 // This is bad because it can be overridden by 'foo(s: String?): String', which is not override-equivalent with K::foo above. 465 // Should be 'foo(s: String): String'. 466 Modality modality = getMinimalModality(effectiveOverridden); 467 Visibility visibility = allInvisible ? Visibilities.INVISIBLE_FAKE : Visibilities.INHERITED; 468 CallableMemberDescriptor mostSpecific = 469 selectMostSpecificMember(effectiveOverridden, 470 new Function1<CallableMemberDescriptor, CallableDescriptor>() { 471 @Override 472 public CallableMemberDescriptor invoke(CallableMemberDescriptor descriptor) { 473 return descriptor; 474 } 475 }); 476 CallableMemberDescriptor fakeOverride = 477 mostSpecific.copy(current, modality, visibility, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false); 478 for (CallableMemberDescriptor descriptor : effectiveOverridden) { 479 fakeOverride.addOverriddenDescriptor(descriptor); 480 } 481 sink.addFakeOverride(fakeOverride); 482 } 483 484 @NotNull 485 private static Modality getMinimalModality(@NotNull Collection<CallableMemberDescriptor> descriptors) { 486 Modality modality = Modality.ABSTRACT; 487 for (CallableMemberDescriptor descriptor : descriptors) { 488 if (descriptor.getModality().compareTo(modality) < 0) { 489 modality = descriptor.getModality(); 490 } 491 } 492 return modality; 493 } 494 495 @NotNull 496 private static Collection<CallableMemberDescriptor> filterVisibleFakeOverrides( 497 @NotNull final ClassDescriptor current, 498 @NotNull Collection<CallableMemberDescriptor> toFilter 499 ) { 500 return CollectionsKt.filter(toFilter, new Function1<CallableMemberDescriptor, Boolean>() { 501 @Override 502 public Boolean invoke(CallableMemberDescriptor descriptor) { 503 //nested class could capture private member, so check for private visibility added 504 return !Visibilities.isPrivate(descriptor.getVisibility()) && 505 Visibilities.isVisibleWithIrrelevantReceiver(descriptor, current); 506 } 507 }); 508 } 509 510 /** 511 * @param <H> is something that handles CallableDescriptor inside 512 * @return 513 */ 514 @NotNull 515 public static <H> Collection<H> extractMembersOverridableInBothWays( 516 @NotNull H overrider, 517 @NotNull @Mutable Collection<H> extractFrom, 518 @NotNull Function1<H, CallableDescriptor> descriptorByHandle, 519 @NotNull Function1<H, Unit> onConflict 520 ) { 521 Collection<H> overridable = new ArrayList<H>(); 522 overridable.add(overrider); 523 CallableDescriptor overriderDescriptor = descriptorByHandle.invoke(overrider); 524 for (Iterator<H> iterator = extractFrom.iterator(); iterator.hasNext(); ) { 525 H candidate = iterator.next(); 526 CallableDescriptor candidateDescriptor = descriptorByHandle.invoke(candidate); 527 if (overrider == candidate) { 528 iterator.remove(); 529 continue; 530 } 531 532 OverrideCompatibilityInfo.Result finalResult = getBothWaysOverridability(overriderDescriptor, candidateDescriptor); 533 534 if (finalResult == OVERRIDABLE) { 535 overridable.add(candidate); 536 iterator.remove(); 537 } 538 else if (finalResult == CONFLICT) { 539 onConflict.invoke(candidate); 540 iterator.remove(); 541 } 542 } 543 return overridable; 544 } 545 546 @Nullable 547 public static OverrideCompatibilityInfo.Result getBothWaysOverridability( 548 CallableDescriptor overriderDescriptor, 549 CallableDescriptor candidateDescriptor 550 ) { 551 OverrideCompatibilityInfo.Result result1 = DEFAULT.isOverridableBy(candidateDescriptor, overriderDescriptor, null).getResult(); 552 OverrideCompatibilityInfo.Result result2 = DEFAULT.isOverridableBy(overriderDescriptor, candidateDescriptor, null).getResult(); 553 554 return result1 == OVERRIDABLE && result2 == OVERRIDABLE 555 ? OVERRIDABLE 556 : ((result1 == CONFLICT || result2 == CONFLICT) ? CONFLICT : INCOMPATIBLE); 557 } 558 559 @NotNull 560 private static Collection<CallableMemberDescriptor> extractMembersOverridableInBothWays( 561 @NotNull final CallableMemberDescriptor overrider, 562 @NotNull Queue<CallableMemberDescriptor> extractFrom, 563 @NotNull final DescriptorSink sink 564 ) { 565 return extractMembersOverridableInBothWays(overrider, extractFrom, 566 // ID 567 new Function1<CallableMemberDescriptor, CallableDescriptor>() { 568 @Override 569 public CallableDescriptor invoke(CallableMemberDescriptor descriptor) { 570 return descriptor; 571 } 572 }, 573 new Function1<CallableMemberDescriptor, Unit>() { 574 @Override 575 public Unit invoke(CallableMemberDescriptor descriptor) { 576 sink.conflict(overrider, descriptor); 577 return Unit.INSTANCE; 578 } 579 }); 580 } 581 582 583 public static void resolveUnknownVisibilityForMember( 584 @NotNull CallableMemberDescriptor memberDescriptor, 585 @Nullable Function1<CallableMemberDescriptor, Unit> cannotInferVisibility 586 ) { 587 for (CallableMemberDescriptor descriptor : memberDescriptor.getOverriddenDescriptors()) { 588 if (descriptor.getVisibility() == Visibilities.INHERITED) { 589 resolveUnknownVisibilityForMember(descriptor, cannotInferVisibility); 590 } 591 } 592 593 if (memberDescriptor.getVisibility() != Visibilities.INHERITED) { 594 return; 595 } 596 597 Visibility maxVisibility = computeVisibilityToInherit(memberDescriptor); 598 Visibility visibilityToInherit; 599 if (maxVisibility == null) { 600 if (cannotInferVisibility != null) { 601 cannotInferVisibility.invoke(memberDescriptor); 602 } 603 visibilityToInherit = Visibilities.PUBLIC; 604 } 605 else { 606 visibilityToInherit = maxVisibility; 607 } 608 609 if (memberDescriptor instanceof PropertyDescriptorImpl) { 610 ((PropertyDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit); 611 for (PropertyAccessorDescriptor accessor : ((PropertyDescriptor) memberDescriptor).getAccessors()) { 612 // If we couldn't infer visibility for property, the diagnostic is already reported, no need to report it again on accessors 613 resolveUnknownVisibilityForMember(accessor, maxVisibility == null ? null : cannotInferVisibility); 614 } 615 } 616 else if (memberDescriptor instanceof FunctionDescriptorImpl) { 617 ((FunctionDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit); 618 } 619 else { 620 assert memberDescriptor instanceof PropertyAccessorDescriptorImpl; 621 ((PropertyAccessorDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit); 622 } 623 } 624 625 @Nullable 626 private static Visibility computeVisibilityToInherit(@NotNull CallableMemberDescriptor memberDescriptor) { 627 Collection<? extends CallableMemberDescriptor> overriddenDescriptors = memberDescriptor.getOverriddenDescriptors(); 628 Visibility maxVisibility = findMaxVisibility(overriddenDescriptors); 629 if (maxVisibility == null) { 630 return null; 631 } 632 if (memberDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { 633 for (CallableMemberDescriptor overridden : overriddenDescriptors) { 634 // An implementation (a non-abstract overridden member) of a fake override should have the maximum possible visibility 635 if (overridden.getModality() != Modality.ABSTRACT && !overridden.getVisibility().equals(maxVisibility)) { 636 return null; 637 } 638 } 639 return maxVisibility; 640 } 641 return maxVisibility.normalize(); 642 } 643 644 @Nullable 645 public static Visibility findMaxVisibility(@NotNull Collection<? extends CallableMemberDescriptor> descriptors) { 646 if (descriptors.isEmpty()) { 647 return Visibilities.DEFAULT_VISIBILITY; 648 } 649 Visibility maxVisibility = null; 650 for (CallableMemberDescriptor descriptor : descriptors) { 651 Visibility visibility = descriptor.getVisibility(); 652 assert visibility != Visibilities.INHERITED : "Visibility should have been computed for " + descriptor; 653 if (maxVisibility == null) { 654 maxVisibility = visibility; 655 continue; 656 } 657 Integer compareResult = Visibilities.compare(visibility, maxVisibility); 658 if (compareResult == null) { 659 maxVisibility = null; 660 } 661 else if (compareResult > 0) { 662 maxVisibility = visibility; 663 } 664 } 665 if (maxVisibility == null) { 666 return null; 667 } 668 for (CallableMemberDescriptor descriptor : descriptors) { 669 Integer compareResult = Visibilities.compare(maxVisibility, descriptor.getVisibility()); 670 if (compareResult == null || compareResult < 0) { 671 return null; 672 } 673 } 674 return maxVisibility; 675 } 676 677 public interface DescriptorSink { 678 void addFakeOverride(@NotNull CallableMemberDescriptor fakeOverride); 679 680 void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent); 681 } 682 683 public static class OverrideCompatibilityInfo { 684 public enum Result { 685 OVERRIDABLE, 686 INCOMPATIBLE, 687 CONFLICT, 688 } 689 690 private static final OverrideCompatibilityInfo SUCCESS = new OverrideCompatibilityInfo(OVERRIDABLE, "SUCCESS"); 691 692 @NotNull 693 public static OverrideCompatibilityInfo success() { 694 return SUCCESS; 695 } 696 697 @NotNull 698 public static OverrideCompatibilityInfo incompatible(@NotNull String debugMessage) { 699 return new OverrideCompatibilityInfo(INCOMPATIBLE, debugMessage); 700 } 701 702 @NotNull 703 public static OverrideCompatibilityInfo conflict(@NotNull String debugMessage) { 704 return new OverrideCompatibilityInfo(CONFLICT, debugMessage); 705 } 706 707 private final Result overridable; 708 private final String debugMessage; 709 710 public OverrideCompatibilityInfo(@NotNull Result success, @NotNull String debugMessage) { 711 this.overridable = success; 712 this.debugMessage = debugMessage; 713 } 714 715 @NotNull 716 public Result getResult() { 717 return overridable; 718 } 719 720 @NotNull 721 public String getDebugMessage() { 722 return debugMessage; 723 } 724 } 725 }