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