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