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