001 /*
002 * Copyright 2010-2013 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.jet.lang.resolve;
018
019 import com.google.common.base.Predicate;
020 import com.google.common.collect.*;
021 import com.intellij.util.Function;
022 import com.intellij.util.containers.ContainerUtil;
023 import org.jetbrains.annotations.NotNull;
024 import org.jetbrains.annotations.Nullable;
025 import org.jetbrains.jet.lang.descriptors.*;
026 import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorImpl;
027 import org.jetbrains.jet.lang.descriptors.impl.PropertyAccessorDescriptorImpl;
028 import org.jetbrains.jet.lang.descriptors.impl.PropertyDescriptorImpl;
029 import org.jetbrains.jet.lang.resolve.name.Name;
030 import org.jetbrains.jet.lang.types.*;
031 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
032
033 import java.util.*;
034
035 import static org.jetbrains.jet.lang.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.CONFLICT;
036 import static org.jetbrains.jet.lang.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE;
037
038 public class OverridingUtil {
039
040 private static final List<ExternalOverridabilityCondition> EXTERNAL_CONDITIONS =
041 ContainerUtil.collect(ServiceLoader.load(
042 ExternalOverridabilityCondition.class,
043 ExternalOverridabilityCondition.class.getClassLoader()).iterator()
044 );
045
046 private OverridingUtil() {
047 }
048
049 private static enum Filtering {
050 RETAIN_OVERRIDING,
051 RETAIN_OVERRIDDEN
052 }
053
054 @NotNull
055 public static <D extends CallableDescriptor> Set<D> filterOutOverridden(@NotNull Set<D> candidateSet) {
056 return filterOverrides(candidateSet, Function.ID, Filtering.RETAIN_OVERRIDING);
057 }
058
059 @NotNull
060 public static <D> Set<D> filterOutOverriding(@NotNull Set<D> candidateSet) {
061 return filterOverrides(candidateSet, Function.ID, Filtering.RETAIN_OVERRIDDEN);
062 }
063
064 @NotNull
065 public static <D> Set<D> filterOutOverridden(
066 @NotNull Set<D> candidateSet,
067 @NotNull Function<? super D, ? extends CallableDescriptor> transform
068 ) {
069 return filterOverrides(candidateSet, transform, Filtering.RETAIN_OVERRIDING);
070 }
071
072 @NotNull
073 private static <D> Set<D> filterOverrides(
074 @NotNull Set<D> candidateSet,
075 @NotNull Function<? super D, ? extends CallableDescriptor> transform,
076 @NotNull Filtering filtering
077 ) {
078 Set<D> candidates = Sets.newLinkedHashSet();
079 outerLoop:
080 for (D meD : candidateSet) {
081 CallableDescriptor me = transform.fun(meD);
082 for (D otherD : candidateSet) {
083 CallableDescriptor other = transform.fun(otherD);
084 if (me == other) continue;
085 if (filtering == Filtering.RETAIN_OVERRIDING) {
086 if (overrides(other, me)) {
087 continue outerLoop;
088 }
089 }
090 else if (filtering == Filtering.RETAIN_OVERRIDDEN) {
091 if (overrides(me, other)) {
092 continue outerLoop;
093 }
094 }
095 else {
096 throw new AssertionError("Unexpected Filtering object: " + filtering);
097 }
098 }
099 for (D otherD : candidates) {
100 CallableDescriptor other = transform.fun(otherD);
101 if (me.getOriginal() == other.getOriginal()
102 && isOverridableBy(other, me).getResult() == OverrideCompatibilityInfo.Result.OVERRIDABLE
103 && isOverridableBy(me, other).getResult() == OverrideCompatibilityInfo.Result.OVERRIDABLE) {
104 continue outerLoop;
105 }
106 }
107 candidates.add(meD);
108 }
109 return candidates;
110 }
111
112 public static <D extends CallableDescriptor> boolean overrides(@NotNull D f, @NotNull D g) {
113 CallableDescriptor originalG = g.getOriginal();
114 for (CallableDescriptor overriddenFunction : getAllOverriddenDescriptors(f)) {
115 if (originalG.equals(overriddenFunction.getOriginal())) return true;
116 }
117 return false;
118 }
119
120 public static Set<CallableDescriptor> getAllOverriddenDescriptors(CallableDescriptor f) {
121 Set<CallableDescriptor> overriddenDescriptors = Sets.newHashSet();
122 collectAllOverriddenDescriptors(f.getOriginal(), overriddenDescriptors);
123 return overriddenDescriptors;
124 }
125
126 private static void collectAllOverriddenDescriptors(
127 @NotNull CallableDescriptor current,
128 @NotNull Set<CallableDescriptor> result
129 ) {
130 if (result.contains(current)) return;
131 for (CallableDescriptor descriptor : current.getOriginal().getOverriddenDescriptors()) {
132 collectAllOverriddenDescriptors(descriptor, result);
133 result.add(descriptor);
134 }
135 }
136
137 @NotNull
138 public static OverrideCompatibilityInfo isOverridableBy(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
139 if (superDescriptor instanceof FunctionDescriptor) {
140 if (!(subDescriptor instanceof FunctionDescriptor)) return OverrideCompatibilityInfo.memberKindMismatch();
141 }
142 else if (superDescriptor instanceof PropertyDescriptor) {
143 if (!(subDescriptor instanceof PropertyDescriptor)) return OverrideCompatibilityInfo.memberKindMismatch();
144 }
145 else {
146 throw new IllegalArgumentException("This type of CallableDescriptor cannot be checked for overridability: " + superDescriptor);
147 }
148
149 // TODO: check outside of this method
150 if (!superDescriptor.getName().equals(subDescriptor.getName())) {
151 return OverrideCompatibilityInfo.nameMismatch();
152 }
153
154 return isOverridableByImpl(superDescriptor, subDescriptor, true);
155 }
156
157 private static List<JetType> compiledValueParameters(CallableDescriptor callableDescriptor) {
158 ReceiverParameterDescriptor receiverParameter = callableDescriptor.getReceiverParameter();
159 ArrayList<JetType> parameters = new ArrayList<JetType>();
160 if (receiverParameter != null) {
161 parameters.add(receiverParameter.getType());
162 }
163 for (ValueParameterDescriptor valueParameterDescriptor : callableDescriptor.getValueParameters()) {
164 parameters.add(valueParameterDescriptor.getType());
165 }
166 return parameters;
167 }
168
169 /**
170 * @param forOverride true for override, false for overload
171 */
172 static OverrideCompatibilityInfo isOverridableByImpl(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor, boolean forOverride) {
173
174 // TODO : Visibility
175
176 if ((superDescriptor.getReceiverParameter() == null) != (subDescriptor.getReceiverParameter() == null)) {
177 return OverrideCompatibilityInfo.receiverPresenceMismatch();
178 }
179
180 if (superDescriptor.getValueParameters().size() != subDescriptor.getValueParameters().size()) {
181 return OverrideCompatibilityInfo.valueParameterNumberMismatch();
182 }
183
184 List<JetType> superValueParameters = compiledValueParameters(superDescriptor);
185 List<JetType> subValueParameters = compiledValueParameters(subDescriptor);
186
187 if (forOverride) {
188 if (superDescriptor.getTypeParameters().size() != subDescriptor.getTypeParameters().size()) {
189 for (int i = 0; i < superValueParameters.size(); ++i) {
190 JetType superValueParameterType = getUpperBound(superValueParameters.get(i));
191 JetType subValueParameterType = getUpperBound(subValueParameters.get(i));
192 // TODO: compare erasure
193 if (!JetTypeChecker.INSTANCE.equalTypes(superValueParameterType, subValueParameterType)) {
194 return OverrideCompatibilityInfo.typeParameterNumberMismatch();
195 }
196 }
197 return OverrideCompatibilityInfo.valueParameterTypeMismatch(null, null, OverrideCompatibilityInfo.Result.CONFLICT);
198 }
199 }
200
201 if (forOverride) {
202
203 List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
204 List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();
205
206 BiMap<TypeConstructor, TypeConstructor> axioms = HashBiMap.create();
207 for (int i = 0, typeParametersSize = superTypeParameters.size(); i < typeParametersSize; i++) {
208 TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i);
209 TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i);
210 axioms.put(superTypeParameter.getTypeConstructor(), subTypeParameter.getTypeConstructor());
211 }
212
213 for (int i = 0, typeParametersSize = superTypeParameters.size(); i < typeParametersSize; i++) {
214 TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i);
215 TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i);
216
217 if (!JetTypeChecker.INSTANCE.equalTypes(superTypeParameter.getUpperBoundsAsType(), subTypeParameter.getUpperBoundsAsType(), axioms)) {
218 return OverrideCompatibilityInfo.boundsMismatch(superTypeParameter, subTypeParameter);
219 }
220 }
221
222 for (int i = 0, unsubstitutedValueParametersSize = superValueParameters.size(); i < unsubstitutedValueParametersSize; i++) {
223 JetType superValueParameter = superValueParameters.get(i);
224 JetType subValueParameter = subValueParameters.get(i);
225
226 boolean bothErrors = superValueParameter.isError() && subValueParameter.isError();
227 if (!bothErrors && !JetTypeChecker.INSTANCE.equalTypes(superValueParameter, subValueParameter, axioms)) {
228 return OverrideCompatibilityInfo.valueParameterTypeMismatch(superValueParameter, subValueParameter, OverrideCompatibilityInfo.Result.INCOMPATIBLE);
229 }
230 }
231
232 for (ExternalOverridabilityCondition externalCondition : EXTERNAL_CONDITIONS) {
233 if (!externalCondition.isOverridable(superDescriptor, subDescriptor)) {
234 return OverrideCompatibilityInfo.externalConditionFailed(externalCondition.getClass());
235 }
236 }
237 }
238 else {
239
240 for (int i = 0; i < superValueParameters.size(); ++i) {
241 JetType superValueParameterType = getUpperBound(superValueParameters.get(i));
242 JetType subValueParameterType = getUpperBound(subValueParameters.get(i));
243 // TODO: compare erasure
244 if (!JetTypeChecker.INSTANCE.equalTypes(superValueParameterType, subValueParameterType)) {
245 return OverrideCompatibilityInfo.valueParameterTypeMismatch(superValueParameterType, subValueParameterType, OverrideCompatibilityInfo.Result.INCOMPATIBLE);
246 }
247 }
248
249 return OverrideCompatibilityInfo.success();
250
251 }
252
253 // TODO : Default values, varargs etc
254
255 return OverrideCompatibilityInfo.success();
256 }
257
258 private static JetType getUpperBound(JetType type) {
259 if (type.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
260 return type;
261 }
262 else if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {
263 return ((TypeParameterDescriptor) type.getConstructor().getDeclarationDescriptor()).getUpperBoundsAsType();
264 }
265 else {
266 throw new IllegalStateException("unknown type constructor: " + type.getConstructor().getClass().getName());
267 }
268 }
269
270 public static boolean isReturnTypeOkForOverride(@NotNull JetTypeChecker typeChecker, @NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
271 TypeSubstitutor typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor);
272 if (typeSubstitutor == null) return false;
273
274 JetType superReturnType = superDescriptor.getReturnType();
275 assert superReturnType != null;
276
277 JetType subReturnType = subDescriptor.getReturnType();
278 assert subReturnType != null;
279
280 JetType substitutedSuperReturnType = typeSubstitutor.substitute(superReturnType, Variance.OUT_VARIANCE);
281 assert substitutedSuperReturnType != null;
282
283 return typeChecker.isSubtypeOf(subReturnType, substitutedSuperReturnType);
284 }
285
286 @Nullable
287 private static TypeSubstitutor prepareTypeSubstitutor(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
288 List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
289 List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();
290 if (subTypeParameters.size() != superTypeParameters.size()) return null;
291
292 Map<TypeConstructor, TypeProjection> substitutionContext = Maps.newHashMap();
293 for (int i = 0; i < superTypeParameters.size(); i++) {
294 TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i);
295 TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i);
296 substitutionContext.put(
297 superTypeParameter.getTypeConstructor(),
298 new TypeProjectionImpl(subTypeParameter.getDefaultType()));
299 }
300 return TypeSubstitutor.create(substitutionContext);
301 }
302
303 public static boolean isPropertyTypeOkForOverride(@NotNull JetTypeChecker typeChecker, @NotNull PropertyDescriptor superDescriptor, @NotNull PropertyDescriptor subDescriptor) {
304 TypeSubstitutor typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor);
305 JetType substitutedSuperReturnType = typeSubstitutor.substitute(superDescriptor.getReturnType(), Variance.OUT_VARIANCE);
306 assert substitutedSuperReturnType != null;
307 if (superDescriptor.isVar() && !typeChecker.equalTypes(subDescriptor.getReturnType(), substitutedSuperReturnType)) {
308 return false;
309 }
310
311 return true;
312 }
313
314 /**
315 * Get overridden descriptors that are declarations or delegations.
316 *
317 * @see CallableMemberDescriptor.Kind#isReal()
318 */
319 public static Collection<CallableMemberDescriptor> getOverriddenDeclarations(CallableMemberDescriptor descriptor) {
320 Map<ClassDescriptor, CallableMemberDescriptor> result = Maps.newHashMap();
321 getOverriddenDeclarations(descriptor, result);
322 return result.values();
323 }
324
325 private static void getOverriddenDeclarations(CallableMemberDescriptor descriptor, Map<ClassDescriptor, CallableMemberDescriptor> r) {
326 if (descriptor.getKind().isReal()) {
327 r.put((ClassDescriptor) descriptor.getContainingDeclaration(), descriptor);
328 }
329 else {
330 if (descriptor.getOverriddenDescriptors().isEmpty()) {
331 throw new IllegalStateException("No overridden descriptors found for (fake override) " + descriptor);
332 }
333 for (CallableMemberDescriptor overridden : descriptor.getOverriddenDescriptors()) {
334 getOverriddenDeclarations(overridden, r);
335 }
336 }
337 }
338
339 public static void bindOverride(CallableMemberDescriptor fromCurrent, CallableMemberDescriptor fromSupertype) {
340 fromCurrent.addOverriddenDescriptor(fromSupertype);
341
342 for (ValueParameterDescriptor parameterFromCurrent : fromCurrent.getValueParameters()) {
343 assert parameterFromCurrent.getIndex() < fromSupertype.getValueParameters().size()
344 : "An override relation between functions implies that they have the same number of value parameters";
345 ValueParameterDescriptor parameterFromSupertype = fromSupertype.getValueParameters().get(parameterFromCurrent.getIndex());
346 parameterFromCurrent.addOverriddenDescriptor(parameterFromSupertype);
347 }
348 }
349
350 public static void generateOverridesInFunctionGroup(
351 @SuppressWarnings("UnusedParameters")
352 @NotNull Name name, //DO NOT DELETE THIS PARAMETER: needed to make sure all descriptors have the same name
353 @NotNull Collection<? extends CallableMemberDescriptor> membersFromSupertypes,
354 @NotNull Collection<? extends CallableMemberDescriptor> membersFromCurrent,
355 @NotNull ClassDescriptor current,
356 @NotNull DescriptorSink sink
357 ) {
358 Collection<CallableMemberDescriptor> notOverridden = Sets.newLinkedHashSet(membersFromSupertypes);
359
360 for (CallableMemberDescriptor fromCurrent : membersFromCurrent) {
361 Collection<CallableMemberDescriptor> bound =
362 extractAndBindOverridesForMember(fromCurrent, membersFromSupertypes, current, sink);
363 notOverridden.removeAll(bound);
364 }
365
366 createAndBindFakeOverrides(current, notOverridden, sink);
367 }
368
369 private static Collection<CallableMemberDescriptor> extractAndBindOverridesForMember(
370 @NotNull CallableMemberDescriptor fromCurrent,
371 @NotNull Collection<? extends CallableMemberDescriptor> descriptorsFromSuper,
372 @NotNull ClassDescriptor current,
373 @NotNull DescriptorSink sink
374 ) {
375 Collection<CallableMemberDescriptor> bound = Lists.newArrayList();
376 for (CallableMemberDescriptor fromSupertype : descriptorsFromSuper) {
377 OverrideCompatibilityInfo.Result result = isOverridableBy(fromSupertype, fromCurrent).getResult();
378
379 boolean isVisible = Visibilities.isVisible(fromSupertype, current);
380 switch (result) {
381 case OVERRIDABLE:
382 if (isVisible) {
383 bindOverride(fromCurrent, fromSupertype);
384 }
385 bound.add(fromSupertype);
386 break;
387 case CONFLICT:
388 if (isVisible) {
389 sink.conflict(fromSupertype, fromCurrent);
390 }
391 bound.add(fromSupertype);
392 break;
393 case INCOMPATIBLE:
394 break;
395 }
396 }
397 return bound;
398 }
399
400 private static void createAndBindFakeOverrides(
401 @NotNull ClassDescriptor current,
402 @NotNull Collection<CallableMemberDescriptor> notOverridden,
403 @NotNull DescriptorSink sink
404 ) {
405 Queue<CallableMemberDescriptor> fromSuperQueue = new LinkedList<CallableMemberDescriptor>(notOverridden);
406 while (!fromSuperQueue.isEmpty()) {
407 CallableMemberDescriptor notOverriddenFromSuper = VisibilityUtil.findMemberWithMaxVisibility(fromSuperQueue);
408 Collection<CallableMemberDescriptor> overridables =
409 extractMembersOverridableInBothWays(notOverriddenFromSuper, fromSuperQueue, sink);
410 createAndBindFakeOverride(overridables, current, sink);
411 }
412 }
413
414 private static boolean isMoreSpecific(@NotNull CallableMemberDescriptor a, @NotNull CallableMemberDescriptor b) {
415 if (a instanceof SimpleFunctionDescriptor) {
416 assert b instanceof SimpleFunctionDescriptor : "b is " + b.getClass();
417
418 JetType aReturnType = a.getReturnType();
419 assert aReturnType != null;
420 JetType bReturnType = b.getReturnType();
421 assert bReturnType != null;
422
423 return JetTypeChecker.INSTANCE.isSubtypeOf(aReturnType, bReturnType);
424 }
425 if (a instanceof PropertyDescriptor) {
426 assert b instanceof PropertyDescriptor : "b is " + b.getClass();
427
428 if (((PropertyDescriptor) a).isVar() || ((PropertyDescriptor) b).isVar()) {
429 return ((PropertyDescriptor) a).isVar();
430 }
431
432 // both vals
433 return JetTypeChecker.INSTANCE.isSubtypeOf(((PropertyDescriptor) a).getType(), ((PropertyDescriptor) b).getType());
434 }
435 throw new IllegalArgumentException("Unexpected callable: " + a.getClass());
436 }
437
438 private static CallableMemberDescriptor selectMostSpecificMemberFromSuper(@NotNull Collection<CallableMemberDescriptor> overridables) {
439 CallableMemberDescriptor result = null;
440 for (CallableMemberDescriptor overridable : overridables) {
441 if (result == null || isMoreSpecific(overridable, result)) {
442 result = overridable;
443 }
444 }
445 return result;
446 }
447
448 private static void createAndBindFakeOverride(
449 @NotNull Collection<CallableMemberDescriptor> overridables,
450 @NotNull ClassDescriptor current,
451 @NotNull DescriptorSink sink
452 ) {
453 Collection<CallableMemberDescriptor> visibleOverridables = filterVisibleFakeOverrides(current, overridables);
454 Modality modality = getMinimalModality(visibleOverridables);
455 boolean allInvisible = visibleOverridables.isEmpty();
456 Collection<CallableMemberDescriptor> effectiveOverridden = allInvisible ? overridables : visibleOverridables;
457 Visibility visibility = allInvisible ? Visibilities.INVISIBLE_FAKE : Visibilities.INHERITED;
458 CallableMemberDescriptor mostSpecific = selectMostSpecificMemberFromSuper(effectiveOverridden);
459 CallableMemberDescriptor fakeOverride =
460 mostSpecific.copy(current, modality, visibility, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false);
461 for (CallableMemberDescriptor descriptor : effectiveOverridden) {
462 bindOverride(fakeOverride, descriptor);
463 }
464 sink.addToScope(fakeOverride);
465 }
466
467 @NotNull
468 private static Modality getMinimalModality(@NotNull Collection<CallableMemberDescriptor> descriptors) {
469 Modality modality = Modality.ABSTRACT;
470 for (CallableMemberDescriptor descriptor : descriptors) {
471 if (descriptor.getModality().compareTo(modality) < 0) {
472 modality = descriptor.getModality();
473 }
474 }
475 return modality;
476 }
477
478 @NotNull
479 private static Collection<CallableMemberDescriptor> filterVisibleFakeOverrides(
480 @NotNull final ClassDescriptor current,
481 @NotNull Collection<CallableMemberDescriptor> toFilter
482 ) {
483 return Collections2.filter(toFilter, new Predicate<CallableMemberDescriptor>() {
484 @Override
485 public boolean apply(@Nullable CallableMemberDescriptor descriptor) {
486 //nested class could capture private member, so check for private visibility added
487 return descriptor != null &&
488 descriptor.getVisibility() != Visibilities.PRIVATE &&
489 Visibilities.isVisible(descriptor, current);
490 }
491 });
492 }
493
494 @NotNull
495 private static Collection<CallableMemberDescriptor> extractMembersOverridableInBothWays(
496 @NotNull CallableMemberDescriptor overrider,
497 @NotNull Queue<CallableMemberDescriptor> extractFrom,
498 @NotNull DescriptorSink sink
499 ) {
500 Collection<CallableMemberDescriptor> overridable = Lists.newArrayList();
501 overridable.add(overrider);
502 for (Iterator<CallableMemberDescriptor> iterator = extractFrom.iterator(); iterator.hasNext(); ) {
503 CallableMemberDescriptor candidate = iterator.next();
504 if (overrider == candidate) {
505 iterator.remove();
506 continue;
507 }
508
509 OverrideCompatibilityInfo.Result result1 = isOverridableBy(candidate, overrider).getResult();
510 OverrideCompatibilityInfo.Result result2 = isOverridableBy(overrider, candidate).getResult();
511 if (result1 == OVERRIDABLE && result2 == OVERRIDABLE) {
512 overridable.add(candidate);
513 iterator.remove();
514 }
515 else if (result1 == CONFLICT || result2 == CONFLICT) {
516 sink.conflict(overrider, candidate);
517 iterator.remove();
518 }
519 }
520 return overridable;
521 }
522
523 public static void resolveUnknownVisibilityForMember(
524 @NotNull CallableMemberDescriptor memberDescriptor,
525 @NotNull NotInferredVisibilitySink sink
526 ) {
527 for (CallableMemberDescriptor descriptor : memberDescriptor.getOverriddenDescriptors()) {
528 if (descriptor.getVisibility() == Visibilities.INHERITED) {
529 resolveUnknownVisibilityForMember(descriptor, sink);
530 }
531 }
532
533 if (memberDescriptor.getVisibility() != Visibilities.INHERITED) {
534 return;
535 }
536
537 Visibility visibilityToInherit = computeVisibilityToInherit(memberDescriptor, sink);
538 if (memberDescriptor instanceof PropertyDescriptorImpl) {
539 ((PropertyDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit);
540 for (PropertyAccessorDescriptor accessor : ((PropertyDescriptor) memberDescriptor).getAccessors()) {
541 resolveUnknownVisibilityForMember(accessor, sink);
542 }
543 }
544 else if (memberDescriptor instanceof FunctionDescriptorImpl) {
545 ((FunctionDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit);
546 }
547 else {
548 assert memberDescriptor instanceof PropertyAccessorDescriptorImpl;
549 ((PropertyAccessorDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit);
550 }
551 }
552
553 @NotNull
554 private static Visibility computeVisibilityToInherit(
555 @NotNull CallableMemberDescriptor memberDescriptor,
556 @NotNull NotInferredVisibilitySink sink
557 ) {
558 Visibility maxVisibility = findMaxVisibility(memberDescriptor.getOverriddenDescriptors());
559 if (maxVisibility == null) {
560 sink.cannotInferVisibility(memberDescriptor);
561 return Visibilities.PUBLIC;
562 }
563 if (memberDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
564 return maxVisibility;
565 }
566 return maxVisibility.normalize();
567 }
568
569 @Nullable
570 private static Visibility findMaxVisibility(@NotNull Collection<? extends CallableMemberDescriptor> descriptors) {
571 if (descriptors.isEmpty()) {
572 return Visibilities.INTERNAL;
573 }
574 Visibility maxVisibility = null;
575 for (CallableMemberDescriptor descriptor : descriptors) {
576 Visibility visibility = descriptor.getVisibility();
577 assert visibility != Visibilities.INHERITED;
578 if (maxVisibility == null) {
579 maxVisibility = visibility;
580 continue;
581 }
582 Integer compareResult = Visibilities.compare(visibility, maxVisibility);
583 if (compareResult == null) {
584 maxVisibility = null;
585 }
586 else if (compareResult > 0) {
587 maxVisibility = visibility;
588 }
589 }
590 if (maxVisibility == null) {
591 return null;
592 }
593 for (CallableMemberDescriptor descriptor : descriptors) {
594 Integer compareResult = Visibilities.compare(maxVisibility, descriptor.getVisibility());
595 if (compareResult == null || compareResult < 0) {
596 return null;
597 }
598 }
599 return maxVisibility;
600 }
601
602 public interface DescriptorSink {
603 void addToScope(@NotNull CallableMemberDescriptor fakeOverride);
604
605 void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent);
606 }
607
608 public interface NotInferredVisibilitySink {
609 void cannotInferVisibility(@NotNull CallableMemberDescriptor descriptor);
610 }
611
612 public static class OverrideCompatibilityInfo {
613
614 public enum Result {
615 OVERRIDABLE,
616 INCOMPATIBLE,
617 CONFLICT,
618 }
619
620 private static final OverrideCompatibilityInfo SUCCESS = new OverrideCompatibilityInfo(Result.OVERRIDABLE, "SUCCESS");
621
622 @NotNull
623 public static OverrideCompatibilityInfo success() {
624 return SUCCESS;
625 }
626
627 @NotNull
628 public static OverrideCompatibilityInfo nameMismatch() {
629 return new OverrideCompatibilityInfo(Result.INCOMPATIBLE, "nameMismatch"); // TODO
630 }
631
632 @NotNull
633 public static OverrideCompatibilityInfo typeParameterNumberMismatch() {
634 return new OverrideCompatibilityInfo(Result.INCOMPATIBLE, "typeParameterNumberMismatch"); // TODO
635 }
636
637 @NotNull
638 public static OverrideCompatibilityInfo receiverPresenceMismatch() {
639 return new OverrideCompatibilityInfo(Result.INCOMPATIBLE, "receiverPresenceMismatch"); // TODO
640 }
641
642 @NotNull
643 public static OverrideCompatibilityInfo valueParameterNumberMismatch() {
644 return new OverrideCompatibilityInfo(Result.INCOMPATIBLE, "valueParameterNumberMismatch"); // TODO
645 }
646
647 @NotNull
648 public static OverrideCompatibilityInfo boundsMismatch(TypeParameterDescriptor superTypeParameter, TypeParameterDescriptor subTypeParameter) {
649 return new OverrideCompatibilityInfo(Result.INCOMPATIBLE, "boundsMismatch"); // TODO
650 }
651
652 @NotNull
653 public static OverrideCompatibilityInfo valueParameterTypeMismatch(JetType superValueParameter, JetType subValueParameter, Result result) {
654 return new OverrideCompatibilityInfo(result, "valueParameterTypeMismatch"); // TODO
655 }
656
657 @NotNull
658 public static OverrideCompatibilityInfo memberKindMismatch() {
659 return new OverrideCompatibilityInfo(Result.INCOMPATIBLE, "memberKindMismatch"); // TODO
660 }
661
662 @NotNull
663 public static OverrideCompatibilityInfo returnTypeMismatch(JetType substitutedSuperReturnType, JetType unsubstitutedSubReturnType) {
664 return new OverrideCompatibilityInfo(Result.CONFLICT, "returnTypeMismatch: " + unsubstitutedSubReturnType + " >< " + substitutedSuperReturnType); // TODO
665 }
666
667 @NotNull
668 public static OverrideCompatibilityInfo varOverriddenByVal() {
669 return new OverrideCompatibilityInfo(Result.INCOMPATIBLE, "varOverriddenByVal"); // TODO
670 }
671
672 @NotNull
673 public static OverrideCompatibilityInfo externalConditionFailed(Class<? extends ExternalOverridabilityCondition> conditionClass) {
674 return new OverrideCompatibilityInfo(Result.INCOMPATIBLE, "externalConditionFailed: " + conditionClass.getName()); // TODO
675 }
676
677 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
678
679 private final Result overridable;
680 private final String message;
681
682 public OverrideCompatibilityInfo(Result success, String message) {
683 this.overridable = success;
684 this.message = message;
685 }
686
687 public Result getResult() {
688 return overridable;
689 }
690
691 public String getMessage() {
692 return message;
693 }
694 }
695 }