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