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