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 }