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