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